support.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /* $NetBSD: support.c,v 1.7 2003/08/07 09:37:11 agc Exp $ */
  2. /*-
  3. * Copyright (c) 1980, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <sys/cdefs.h>
  31. #ifndef lint
  32. #if 0
  33. static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 5/31/93";
  34. #else
  35. __RCSID("$NetBSD: support.c,v 1.7 2003/08/07 09:37:11 agc Exp $");
  36. #endif
  37. #endif /* not lint */
  38. #include <curses.h>
  39. #include <string.h>
  40. #include "deck.h"
  41. #include "cribbage.h"
  42. #include "cribcur.h"
  43. #define NTV 10 /* number scores to test */
  44. /* score to test reachability of, and order to test them in */
  45. const int tv[NTV] = {8, 7, 9, 6, 11, 12, 13, 14, 10, 5};
  46. /*
  47. * computer chooses what to play in pegging...
  48. * only called if no playable card will score points
  49. */
  50. int
  51. cchose(h, n, s)
  52. const CARD h[];
  53. int n, s;
  54. {
  55. int i, j, l;
  56. if (n <= 1)
  57. return (0);
  58. if (s < 4) { /* try for good value */
  59. if ((j = anysumto(h, n, s, 4)) >= 0)
  60. return (j);
  61. if ((j = anysumto(h, n, s, 3)) >= 0 && s == 0)
  62. return (j);
  63. }
  64. if (s > 0 && s < 20) {
  65. /* try for retaliation to 31 */
  66. for (i = 1; i <= 10; i++) {
  67. if ((j = anysumto(h, n, s, 21 - i)) >= 0) {
  68. if ((l = numofval(h, n, i)) > 0) {
  69. if (l > 1 || VAL(h[j].rank) != i)
  70. return (j);
  71. }
  72. }
  73. }
  74. }
  75. if (s < 15) {
  76. /* for retaliation after 15 */
  77. for (i = 0; i < NTV; i++) {
  78. if ((j = anysumto(h, n, s, tv[i])) >= 0) {
  79. if ((l = numofval(h, n, 15 - tv[i])) > 0) {
  80. if (l > 1 ||
  81. VAL(h[j].rank) != 15 - tv[i])
  82. return (j);
  83. }
  84. }
  85. }
  86. }
  87. j = -1;
  88. /* remember: h is sorted */
  89. for (i = n - 1; i >= 0; --i) {
  90. l = s + VAL(h[i].rank);
  91. if (l > 31)
  92. continue;
  93. if (l != 5 && l != 10 && l != 21) {
  94. j = i;
  95. break;
  96. }
  97. }
  98. if (j >= 0)
  99. return (j);
  100. for (i = n - 1; i >= 0; --i) {
  101. l = s + VAL(h[i].rank);
  102. if (l > 31)
  103. continue;
  104. if (j < 0)
  105. j = i;
  106. if (l != 5 && l != 21) {
  107. j = i;
  108. break;
  109. }
  110. }
  111. return (j);
  112. }
  113. /*
  114. * plyrhand:
  115. * Evaluate and score a player hand or crib
  116. */
  117. int
  118. plyrhand(hand, s)
  119. const CARD hand[];
  120. const char *s;
  121. {
  122. static char prompt[BUFSIZ];
  123. int i, j;
  124. BOOLEAN win;
  125. prhand(hand, CINHAND, Playwin, FALSE);
  126. (void) sprintf(prompt, "Your %s scores ", s);
  127. i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain);
  128. if ((j = number(0, 29, prompt)) == 19)
  129. j = 0;
  130. if (i != j) {
  131. if (i < j) {
  132. win = chkscr(&pscore, i);
  133. msg("It's really only %d points; I get %d", i, 2);
  134. if (!win)
  135. win = chkscr(&cscore, 2);
  136. } else {
  137. win = chkscr(&pscore, j);
  138. msg("You should have taken %d, not %d!", i, j);
  139. }
  140. if (explain)
  141. msg("Explanation: %s", explan);
  142. do_wait();
  143. } else
  144. win = chkscr(&pscore, i);
  145. return (win);
  146. }
  147. /*
  148. * comphand:
  149. * Handle scoring and displaying the computers hand
  150. */
  151. int
  152. comphand(h, s)
  153. const CARD h[];
  154. const char *s;
  155. {
  156. int j;
  157. j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE);
  158. prhand(h, CINHAND, Compwin, FALSE);
  159. msg("My %s scores %d", s, (j == 0 ? 19 : j));
  160. return (chkscr(&cscore, j));
  161. }
  162. /*
  163. * chkscr:
  164. * Add inc to scr and test for > glimit, printing on the scoring
  165. * board while we're at it.
  166. */
  167. int Lastscore[2] = {-1, -1};
  168. int
  169. chkscr(scr, inc)
  170. int *scr, inc;
  171. {
  172. BOOLEAN myturn;
  173. myturn = (scr == &cscore);
  174. if (inc != 0) {
  175. prpeg(Lastscore[(int)myturn], '.', myturn);
  176. Lastscore[(int)myturn] = *scr;
  177. *scr += inc;
  178. prpeg(*scr, PEG, myturn);
  179. refresh();
  180. }
  181. return (*scr >= glimit);
  182. }
  183. /*
  184. * prpeg:
  185. * Put out the peg character on the score board and put the
  186. * score up on the board.
  187. */
  188. void
  189. prpeg(score, peg, myturn)
  190. int score;
  191. int peg;
  192. BOOLEAN myturn;
  193. {
  194. int y, x;
  195. if (!myturn)
  196. y = SCORE_Y + 2;
  197. else
  198. y = SCORE_Y + 5;
  199. if (score <= 0 || score >= glimit) {
  200. if (peg == '.')
  201. peg = ' ';
  202. if (score == 0)
  203. x = SCORE_X + 2;
  204. else {
  205. x = SCORE_X + 2;
  206. y++;
  207. }
  208. } else {
  209. x = (score - 1) % 30;
  210. if (score > 90 || (score > 30 && score <= 60)) {
  211. y++;
  212. x = 29 - x;
  213. }
  214. x += x / 5;
  215. x += SCORE_X + 3;
  216. }
  217. mvaddch(y, x, peg);
  218. mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score);
  219. }
  220. /*
  221. * cdiscard -- the computer figures out what is the best discard for
  222. * the crib and puts the best two cards at the end
  223. */
  224. void
  225. cdiscard(mycrib)
  226. BOOLEAN mycrib;
  227. {
  228. CARD d[CARDS], h[FULLHAND], cb[2];
  229. int i, j, k;
  230. int nc, ns;
  231. long sums[15];
  232. static int undo1[15] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
  233. static int undo2[15] = {1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5, 4, 5, 5};
  234. makedeck(d);
  235. nc = CARDS;
  236. for (i = 0; i < knownum; i++) { /* get all other cards */
  237. cremove(known[i], d, nc--);
  238. }
  239. for (i = 0; i < 15; i++)
  240. sums[i] = 0L;
  241. ns = 0;
  242. for (i = 0; i < (FULLHAND - 1); i++) {
  243. cb[0] = chand[i];
  244. for (j = i + 1; j < FULLHAND; j++) {
  245. cb[1] = chand[j];
  246. for (k = 0; k < FULLHAND; k++)
  247. h[k] = chand[k];
  248. cremove(chand[i], h, FULLHAND);
  249. cremove(chand[j], h, FULLHAND - 1);
  250. for (k = 0; k < nc; k++) {
  251. sums[ns] +=
  252. scorehand(h, d[k], CINHAND, TRUE, FALSE);
  253. if (mycrib)
  254. sums[ns] += adjust(cb, d[k]);
  255. else
  256. sums[ns] -= adjust(cb, d[k]);
  257. }
  258. ++ns;
  259. }
  260. }
  261. j = 0;
  262. for (i = 1; i < 15; i++)
  263. if (sums[i] > sums[j])
  264. j = i;
  265. for (k = 0; k < FULLHAND; k++)
  266. h[k] = chand[k];
  267. cremove(h[undo1[j]], chand, FULLHAND);
  268. cremove(h[undo2[j]], chand, FULLHAND - 1);
  269. chand[4] = h[undo1[j]];
  270. chand[5] = h[undo2[j]];
  271. }
  272. /*
  273. * returns true if some card in hand can be played without exceeding 31
  274. */
  275. int
  276. anymove(hand, n, sum)
  277. const CARD hand[];
  278. int n, sum;
  279. {
  280. int i, j;
  281. if (n < 1)
  282. return (FALSE);
  283. j = hand[0].rank;
  284. for (i = 1; i < n; i++) {
  285. if (hand[i].rank < j)
  286. j = hand[i].rank;
  287. }
  288. return (sum + VAL(j) <= 31);
  289. }
  290. /*
  291. * anysumto returns the index (0 <= i < n) of the card in hand that brings
  292. * the s up to t, or -1 if there is none
  293. */
  294. int
  295. anysumto(hand, n, s, t)
  296. const CARD hand[];
  297. int n, s, t;
  298. {
  299. int i;
  300. for (i = 0; i < n; i++) {
  301. if (s + VAL(hand[i].rank) == t)
  302. return (i);
  303. }
  304. return (-1);
  305. }
  306. /*
  307. * return the number of cards in h having the given rank value
  308. */
  309. int
  310. numofval(h, n, v)
  311. const CARD h[];
  312. int n, v;
  313. {
  314. int i, j;
  315. j = 0;
  316. for (i = 0; i < n; i++) {
  317. if (VAL(h[i].rank) == v)
  318. ++j;
  319. }
  320. return (j);
  321. }
  322. /*
  323. * makeknown remembers all n cards in h for future recall
  324. */
  325. void
  326. makeknown(h, n)
  327. const CARD h[];
  328. int n;
  329. {
  330. int i;
  331. for (i = 0; i < n; i++)
  332. known[knownum++] = h[i];
  333. }