comp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /* $NetBSD: comp.c,v 1.9 2003/08/07 09:37:24 agc Exp $ */
  2. /*
  3. * Copyright (c) 1982, 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[] = "@(#)comp.c 8.1 (Berkeley) 5/31/93";
  34. #else
  35. __RCSID("$NetBSD: comp.c,v 1.9 2003/08/07 09:37:24 agc Exp $");
  36. #endif
  37. #endif /* not lint */
  38. # include "mille.h"
  39. /*
  40. * @(#)comp.c 1.1 (Berkeley) 4/1/82
  41. */
  42. # define V_VALUABLE 40
  43. void
  44. calcmove()
  45. {
  46. CARD card;
  47. int *value;
  48. PLAY *pp, *op;
  49. bool foundend, cango, canstop, foundlow;
  50. unsgn int i, count200, badcount, nummin, nummax, diff;
  51. int curmin, curmax;
  52. CARD safe, oppos;
  53. int valbuf[HAND_SZ], count[NUM_CARDS];
  54. bool playit[HAND_SZ];
  55. wmove(Score, ERR_Y, ERR_X); /* get rid of error messages */
  56. wclrtoeol(Score);
  57. pp = &Player[COMP];
  58. op = &Player[PLAYER];
  59. safe = 0;
  60. cango = 0;
  61. canstop = FALSE;
  62. foundend = FALSE;
  63. /* Try for a Coup Forre, and see what we have. */
  64. for (i = 0; i < NUM_CARDS; i++)
  65. count[i] = 0;
  66. for (i = 0; i < HAND_SZ; i++) {
  67. card = pp->hand[i];
  68. switch (card) {
  69. case C_STOP: case C_CRASH:
  70. case C_FLAT: case C_EMPTY:
  71. if ((playit[i] = canplay(pp, op, card)) != 0)
  72. canstop = TRUE;
  73. goto norm;
  74. case C_LIMIT:
  75. if ((playit[i] = canplay(pp, op, card))
  76. && Numseen[C_25] == Numcards[C_25]
  77. && Numseen[C_50] == Numcards[C_50])
  78. canstop = TRUE;
  79. goto norm;
  80. case C_25: case C_50: case C_75:
  81. case C_100: case C_200:
  82. if ((playit[i] = canplay(pp, op, card))
  83. && pp->mileage + Value[card] == End)
  84. foundend = TRUE;
  85. goto norm;
  86. default:
  87. playit[i] = canplay(pp, op, card);
  88. norm:
  89. if (playit[i])
  90. ++cango;
  91. break;
  92. case C_GAS_SAFE: case C_DRIVE_SAFE:
  93. case C_SPARE_SAFE: case C_RIGHT_WAY:
  94. if (pp->battle == opposite(card) ||
  95. (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
  96. Movetype = M_PLAY;
  97. Card_no = i;
  98. return;
  99. }
  100. ++safe;
  101. playit[i] = TRUE;
  102. break;
  103. }
  104. if (card >= 0)
  105. ++count[card];
  106. }
  107. /* No Coup Forre. Draw to fill hand, then restart, as needed. */
  108. if (pp->hand[0] == C_INIT && Topcard > Deck) {
  109. Movetype = M_DRAW;
  110. return;
  111. }
  112. #ifdef DEBUG
  113. if (Debug)
  114. fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
  115. cango, canstop, safe);
  116. #endif
  117. if (foundend)
  118. foundend = !check_ext(TRUE);
  119. for (i = 0; safe && i < HAND_SZ; i++) {
  120. if (is_safety(pp->hand[i])) {
  121. if (onecard(op) || (foundend && cango && !canstop)) {
  122. #ifdef DEBUG
  123. if (Debug)
  124. fprintf(outf,
  125. "CALCMOVE: onecard(op) = %d, foundend = %d\n",
  126. onecard(op), foundend);
  127. #endif
  128. playsafe:
  129. Movetype = M_PLAY;
  130. Card_no = i;
  131. return;
  132. }
  133. oppos = opposite(pp->hand[i]);
  134. if (Numseen[oppos] == Numcards[oppos] &&
  135. !(pp->hand[i] == C_RIGHT_WAY &&
  136. Numseen[C_LIMIT] != Numcards[C_LIMIT]))
  137. goto playsafe;
  138. else if (!cango
  139. && (op->can_go || !pp->can_go || Topcard < Deck)) {
  140. card = (Topcard - Deck) - roll(1, 10);
  141. if ((!pp->mileage) != (!op->mileage))
  142. card -= 7;
  143. #ifdef DEBUG
  144. if (Debug)
  145. fprintf(outf,
  146. "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
  147. card, DECK_SZ / 4);
  148. #endif
  149. if (card < DECK_SZ / 4)
  150. goto playsafe;
  151. }
  152. safe--;
  153. playit[i] = cango;
  154. }
  155. }
  156. if (!pp->can_go && !is_repair(pp->battle))
  157. Numneed[opposite(pp->battle)]++;
  158. redoit:
  159. foundlow = (cango || count[C_END_LIMIT] != 0
  160. || Numseen[C_LIMIT] == Numcards[C_LIMIT]
  161. || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
  162. foundend = FALSE;
  163. count200 = pp->nummiles[C_200];
  164. badcount = 0;
  165. curmax = -1;
  166. curmin = 101;
  167. nummin = -1;
  168. nummax = -1;
  169. value = valbuf;
  170. for (i = 0; i < HAND_SZ; i++) {
  171. card = pp->hand[i];
  172. if (is_safety(card) || playit[i] == (cango != 0)) {
  173. #ifdef DEBUG
  174. if (Debug)
  175. fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
  176. C_name[card]);
  177. #endif
  178. switch (card) {
  179. case C_25: case C_50:
  180. diff = End - pp->mileage;
  181. /* avoid getting too close */
  182. if (Topcard > Deck && cango && diff <= 100
  183. && (int)diff / Value[card] > count[card]
  184. && (card == C_25 || diff % 50 == 0)) {
  185. if (card == C_50 && diff - 50 == 25
  186. && count[C_25] > 0)
  187. goto okay;
  188. *value = 0;
  189. if (--cango <= 0)
  190. goto redoit;
  191. break;
  192. }
  193. okay:
  194. *value = (Value[card] >> 3);
  195. if (pp->speed == C_LIMIT)
  196. ++*value;
  197. else
  198. --*value;
  199. if (!foundlow
  200. && (card == C_50 || count[C_50] == 0)) {
  201. *value = (pp->mileage ? 10 : 20);
  202. foundlow = TRUE;
  203. }
  204. goto miles;
  205. case C_200:
  206. if (++count200 > 2) {
  207. *value = 0;
  208. break;
  209. }
  210. case C_75: case C_100:
  211. *value = (Value[card] >> 3);
  212. if (pp->speed == C_LIMIT)
  213. --*value;
  214. else
  215. ++*value;
  216. miles:
  217. if (pp->mileage + Value[card] > End)
  218. *value = (End == 700 ? card : 0);
  219. else if (pp->mileage + Value[card] == End) {
  220. *value = (foundend ? card : V_VALUABLE);
  221. foundend = TRUE;
  222. }
  223. break;
  224. case C_END_LIMIT:
  225. if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
  226. *value = (pp->safety[S_RIGHT_WAY] ==
  227. S_PLAYED ? -1 : 1);
  228. else if (pp->speed == C_LIMIT &&
  229. End - pp->mileage <= 50)
  230. *value = 1;
  231. else if (pp->speed == C_LIMIT
  232. || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
  233. safe = S_RIGHT_WAY;
  234. oppos = C_LIMIT;
  235. goto repair;
  236. }
  237. else {
  238. *value = 0;
  239. --count[C_END_LIMIT];
  240. }
  241. break;
  242. case C_REPAIRS: case C_SPARE: case C_GAS:
  243. safe = safety(card) - S_CONV;
  244. oppos = opposite(card);
  245. if (pp->safety[safe] != S_UNKNOWN)
  246. *value = (pp->safety[safe] ==
  247. S_PLAYED ? -1 : 1);
  248. else if (pp->battle != oppos
  249. && (Numseen[oppos] == Numcards[oppos] ||
  250. Numseen[oppos] + count[card] >
  251. Numcards[oppos])) {
  252. *value = 0;
  253. --count[card];
  254. }
  255. else {
  256. repair:
  257. *value = Numcards[oppos] * 6;
  258. *value += Numseen[card] -
  259. Numseen[oppos];
  260. if (!cango)
  261. *value /= (count[card]*count[card]);
  262. count[card]--;
  263. }
  264. break;
  265. case C_GO:
  266. if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
  267. *value = (pp->safety[S_RIGHT_WAY] ==
  268. S_PLAYED ? -1 : 2);
  269. else if (pp->can_go
  270. && Numgos + count[C_GO] == Numneed[C_GO]) {
  271. *value = 0;
  272. --count[C_GO];
  273. }
  274. else {
  275. *value = Numneed[C_GO] * 3;
  276. *value += (Numseen[C_GO] - Numgos);
  277. *value /= (count[C_GO] * count[C_GO]);
  278. count[C_GO]--;
  279. }
  280. break;
  281. case C_LIMIT:
  282. if (op->mileage + 50 >= End) {
  283. *value = (End == 700 && !cango);
  284. break;
  285. }
  286. if (canstop || (cango && !op->can_go))
  287. *value = 1;
  288. else {
  289. *value = (pp->safety[S_RIGHT_WAY] !=
  290. S_UNKNOWN ? 2 : 3);
  291. safe = S_RIGHT_WAY;
  292. oppos = C_END_LIMIT;
  293. goto normbad;
  294. }
  295. break;
  296. case C_CRASH: case C_EMPTY: case C_FLAT:
  297. safe = safety(card) - S_CONV;
  298. oppos = opposite(card);
  299. *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
  300. normbad:
  301. if (op->safety[safe] == S_PLAYED)
  302. *value = -1;
  303. else {
  304. *value *= Numneed[oppos] +
  305. Numseen[oppos] + 2;
  306. if (!pp->mileage || foundend ||
  307. onecard(op))
  308. *value += 5;
  309. if (op->mileage == 0 || onecard(op))
  310. *value += 5;
  311. if (op->speed == C_LIMIT)
  312. *value -= 3;
  313. if (cango &&
  314. pp->safety[safe] != S_UNKNOWN)
  315. *value += 3;
  316. if (!cango)
  317. *value /= ++badcount;
  318. }
  319. break;
  320. case C_STOP:
  321. if (op->safety[S_RIGHT_WAY] == S_PLAYED)
  322. *value = -1;
  323. else {
  324. *value = (pp->safety[S_RIGHT_WAY] !=
  325. S_UNKNOWN ? 3 : 4);
  326. *value *= Numcards[C_STOP] +
  327. Numseen[C_GO];
  328. if (!pp->mileage || foundend ||
  329. onecard(op))
  330. *value += 5;
  331. if (!cango)
  332. *value /= ++badcount;
  333. if (op->mileage == 0)
  334. *value += 5;
  335. if ((card == C_LIMIT &&
  336. op->speed == C_LIMIT) ||
  337. !op->can_go)
  338. *value -= 5;
  339. if (cango && pp->safety[S_RIGHT_WAY] !=
  340. S_UNKNOWN)
  341. *value += 5;
  342. }
  343. break;
  344. case C_GAS_SAFE: case C_DRIVE_SAFE:
  345. case C_SPARE_SAFE: case C_RIGHT_WAY:
  346. *value = cango ? 0 : 101;
  347. break;
  348. case C_INIT:
  349. *value = 0;
  350. break;
  351. }
  352. }
  353. else
  354. *value = cango ? 0 : 101;
  355. if (card != C_INIT) {
  356. if (*value >= curmax) {
  357. nummax = i;
  358. curmax = *value;
  359. }
  360. if (*value <= curmin) {
  361. nummin = i;
  362. curmin = *value;
  363. }
  364. }
  365. #ifdef DEBUG
  366. if (Debug)
  367. mvprintw(i + 6, 2, "%3d %-14s", *value,
  368. C_name[pp->hand[i]]);
  369. #endif
  370. value++;
  371. }
  372. if (!pp->can_go && !is_repair(pp->battle))
  373. Numneed[opposite(pp->battle)]++;
  374. if (cango) {
  375. play_it:
  376. mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
  377. Movetype = M_PLAY;
  378. Card_no = nummax;
  379. }
  380. else {
  381. if (is_safety(pp->hand[nummin])) { /* NEVER discard a safety */
  382. nummax = nummin;
  383. goto play_it;
  384. }
  385. mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
  386. Movetype = M_DISCARD;
  387. Card_no = nummin;
  388. }
  389. mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
  390. }
  391. /*
  392. * Return true if the given player could conceivably win with his next card.
  393. */
  394. int
  395. onecard(pp)
  396. const PLAY *pp;
  397. {
  398. CARD bat, spd, card;
  399. bat = pp->battle;
  400. spd = pp->speed;
  401. card = -1;
  402. if (pp->can_go || ((is_repair(bat) || bat == C_STOP || spd == C_LIMIT) &&
  403. Numseen[S_RIGHT_WAY] != 0) ||
  404. (bat >= 0 && Numseen[safety(bat)] != 0))
  405. switch (End - pp->mileage) {
  406. case 200:
  407. if (pp->nummiles[C_200] == 2)
  408. return FALSE;
  409. card = C_200;
  410. /* FALLTHROUGH */
  411. case 100:
  412. case 75:
  413. if (card == -1)
  414. card = (End - pp->mileage == 75 ? C_75 : C_100);
  415. if (spd == C_LIMIT)
  416. return Numseen[S_RIGHT_WAY] == 0;
  417. case 50:
  418. case 25:
  419. if (card == -1)
  420. card = (End - pp->mileage == 25 ? C_25 : C_50);
  421. return Numseen[card] != Numcards[card];
  422. }
  423. return FALSE;
  424. }
  425. int
  426. canplay(pp, op, card)
  427. const PLAY *pp, *op;
  428. CARD card;
  429. {
  430. switch (card) {
  431. case C_200:
  432. if (pp->nummiles[C_200] == 2)
  433. break;
  434. /* FALLTHROUGH */
  435. case C_75: case C_100:
  436. if (pp->speed == C_LIMIT)
  437. break;
  438. /* FALLTHROUGH */
  439. case C_50:
  440. if (pp->mileage + Value[card] > End)
  441. break;
  442. /* FALLTHROUGH */
  443. case C_25:
  444. if (pp->can_go)
  445. return TRUE;
  446. break;
  447. case C_EMPTY: case C_FLAT: case C_CRASH:
  448. case C_STOP:
  449. if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
  450. return TRUE;
  451. break;
  452. case C_LIMIT:
  453. if (op->speed != C_LIMIT &&
  454. op->safety[S_RIGHT_WAY] != S_PLAYED &&
  455. op->mileage + 50 < End)
  456. return TRUE;
  457. break;
  458. case C_GAS: case C_SPARE: case C_REPAIRS:
  459. if (pp->battle == opposite(card))
  460. return TRUE;
  461. break;
  462. case C_GO:
  463. if (!pp->can_go &&
  464. (is_repair(pp->battle) || pp->battle == C_STOP))
  465. return TRUE;
  466. break;
  467. case C_END_LIMIT:
  468. if (pp->speed == C_LIMIT)
  469. return TRUE;
  470. }
  471. return FALSE;
  472. }