2 * Copyright (c) 1982, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)comp.c 8.1 (Berkeley) 5/31/93
34 * $FreeBSD: src/games/mille/comp.c,v 1.5 1999/12/12 06:17:24 billf Exp $
35 * $DragonFly: src/games/mille/comp.c,v 1.2 2003/06/17 04:25:24 dillon Exp $
41 * @(#)comp.c 1.1 (Berkeley) 4/1/82
44 # define V_VALUABLE 40
52 bool foundend, cango, canstop, foundlow;
53 unsgn int i, count200, badcount, nummin, nummax, diff;
56 int valbuf[HAND_SZ], count[NUM_CARDS];
59 wmove(Score, ERR_Y, ERR_X); /* get rid of error messages */
68 /* Try for a Coup Forre, and see what we have. */
69 for (i = 0; i < NUM_CARDS; i++)
71 for (i = 0; i < HAND_SZ; i++) {
74 case C_STOP: case C_CRASH:
75 case C_FLAT: case C_EMPTY:
76 if ((playit[i] = canplay(pp, op, card)) != NULL)
80 if ((playit[i] = canplay(pp, op, card))
81 && Numseen[C_25] == Numcards[C_25]
82 && Numseen[C_50] == Numcards[C_50])
85 case C_25: case C_50: case C_75:
86 case C_100: case C_200:
87 if ((playit[i] = canplay(pp, op, card))
88 && pp->mileage + Value[card] == End)
92 playit[i] = canplay(pp, op, card);
97 case C_GAS_SAFE: case C_DRIVE_SAFE:
98 case C_SPARE_SAFE: case C_RIGHT_WAY:
99 if (pp->battle == opposite(card) ||
100 (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
113 /* No Coup Forre. Draw to fill hand, then restart, as needed. */
114 if (pp->hand[0] == C_INIT && Topcard > Deck) {
121 fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
122 cango, canstop, safe);
125 foundend = !check_ext(TRUE);
126 for (i = 0; safe && i < HAND_SZ; i++) {
127 if (issafety(pp->hand[i])) {
128 if (onecard(op) || (foundend && cango && !canstop)) {
132 "CALCMOVE: onecard(op) = %d, foundend = %d\n",
133 onecard(op), foundend);
140 oppos = opposite(pp->hand[i]);
141 if (Numseen[oppos] == Numcards[oppos] &&
142 !(pp->hand[i] == C_RIGHT_WAY &&
143 Numseen[C_LIMIT] != Numcards[C_LIMIT]))
146 && (op->can_go || !pp->can_go || Topcard < Deck)) {
147 card = (Topcard - Deck) - roll(1, 10);
148 if ((!pp->mileage) != (!op->mileage))
153 "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
156 if (card < DECK_SZ / 4)
163 if (!pp->can_go && !isrepair(pp->battle))
164 Numneed[opposite(pp->battle)]++;
166 foundlow = (cango || count[C_END_LIMIT] != 0
167 || Numseen[C_LIMIT] == Numcards[C_LIMIT]
168 || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
170 count200 = pp->nummiles[C_200];
177 for (i = 0; i < HAND_SZ; i++) {
179 if (issafety(card) || playit[i] == (cango != 0)) {
182 fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
186 case C_25: case C_50:
187 diff = End - pp->mileage;
188 /* avoid getting too close */
189 if (Topcard > Deck && cango && diff <= 100
190 && diff / Value[card] > count[card]
191 && (card == C_25 || diff % 50 == 0)) {
192 if (card == C_50 && diff - 50 == 25
201 *value = (Value[card] >> 3);
202 if (pp->speed == C_LIMIT)
207 && (card == C_50 || count[C_50] == 0)) {
208 *value = (pp->mileage ? 10 : 20);
213 if (++count200 > 2) {
217 case C_75: case C_100:
218 *value = (Value[card] >> 3);
219 if (pp->speed == C_LIMIT)
224 if (pp->mileage + Value[card] > End)
225 *value = (End == 700 ? card : 0);
226 else if (pp->mileage + Value[card] == End) {
227 *value = (foundend ? card : V_VALUABLE);
232 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
233 *value = (pp->safety[S_RIGHT_WAY] ==
235 else if (pp->speed == C_LIMIT &&
236 End - pp->mileage <= 50)
238 else if (pp->speed == C_LIMIT
239 || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
246 --count[C_END_LIMIT];
249 case C_REPAIRS: case C_SPARE: case C_GAS:
250 safe = safety(card) - S_CONV;
251 oppos = opposite(card);
252 if (pp->safety[safe] != S_UNKNOWN)
253 *value = (pp->safety[safe] ==
255 else if (pp->battle != oppos
256 && (Numseen[oppos] == Numcards[oppos] ||
257 Numseen[oppos] + count[card] >
264 *value = Numcards[oppos] * 6;
265 *value += Numseen[card] -
268 *value /= (count[card]*count[card]);
273 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
274 *value = (pp->safety[S_RIGHT_WAY] ==
277 && Numgos + count[C_GO] == Numneed[C_GO]) {
282 *value = Numneed[C_GO] * 3;
283 *value += (Numseen[C_GO] - Numgos);
284 *value /= (count[C_GO] * count[C_GO]);
289 if (op->mileage + 50 >= End) {
290 *value = (End == 700 && !cango);
293 if (canstop || (cango && !op->can_go))
296 *value = (pp->safety[S_RIGHT_WAY] !=
303 case C_CRASH: case C_EMPTY: case C_FLAT:
304 safe = safety(card) - S_CONV;
305 oppos = opposite(card);
306 *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
308 if (op->safety[safe] == S_PLAYED)
311 *value *= Numneed[oppos] +
313 if (!pp->mileage || foundend ||
316 if (op->mileage == 0 || onecard(op))
318 if (op->speed == C_LIMIT)
321 pp->safety[safe] != S_UNKNOWN)
324 *value /= ++badcount;
328 if (op->safety[S_RIGHT_WAY] == S_PLAYED)
331 *value = (pp->safety[S_RIGHT_WAY] !=
333 *value *= Numcards[C_STOP] +
335 if (!pp->mileage || foundend ||
339 *value /= ++badcount;
340 if (op->mileage == 0)
342 if ((card == C_LIMIT &&
343 op->speed == C_LIMIT) ||
346 if (cango && pp->safety[S_RIGHT_WAY] !=
351 case C_GAS_SAFE: case C_DRIVE_SAFE:
352 case C_SPARE_SAFE: case C_RIGHT_WAY:
353 *value = cango ? 0 : 101;
361 *value = cango ? 0 : 101;
362 if (card != C_INIT) {
363 if (*value >= curmax) {
367 if (*value <= curmin) {
374 mvprintw(i + 6, 2, "%3d %-14s", *value,
375 C_name[pp->hand[i]]);
379 if (!pp->can_go && !isrepair(pp->battle))
380 Numneed[opposite(pp->battle)]++;
383 mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
388 if (issafety(pp->hand[nummin])) { /* NEVER discard a safety */
392 mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
393 Movetype = M_DISCARD;
396 mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
400 * Return true if the given player could conceivably win with his next card.
411 if (pp->can_go || ((isrepair(bat) || bat == C_STOP || spd == C_LIMIT) &&
412 Numseen[S_RIGHT_WAY] != 0) ||
413 (bat >= 0 && Numseen[safety(bat)] != 0))
414 switch (End - pp->mileage) {
416 if (pp->nummiles[C_200] == 2)
423 card = (End - pp->mileage == 75 ? C_75 : C_100);
425 return Numseen[S_RIGHT_WAY] == 0;
429 card = (End - pp->mileage == 25 ? C_25 : C_50);
430 return Numseen[card] != Numcards[card];
436 canplay(pp, op, card)
442 if (pp->nummiles[C_200] == 2)
445 case C_75: case C_100:
446 if (pp->speed == C_LIMIT)
450 if (pp->mileage + Value[card] > End)
457 case C_EMPTY: case C_FLAT: case C_CRASH:
459 if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
463 if (op->speed != C_LIMIT &&
464 op->safety[S_RIGHT_WAY] != S_PLAYED &&
465 op->mileage + 50 < End)
468 case C_GAS: case C_SPARE: case C_REPAIRS:
469 if (pp->battle == opposite(card))
474 (isrepair(pp->battle) || pp->battle == C_STOP))
478 if (pp->speed == C_LIMIT)