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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#)comp.c 8.1 (Berkeley) 5/31/93
30 * $FreeBSD: src/games/mille/comp.c,v 1.5 1999/12/12 06:17:24 billf Exp $
31 * $DragonFly: src/games/mille/comp.c,v 1.4 2008/06/05 18:06:30 swildner Exp $
37 * @(#)comp.c 1.1 (Berkeley) 4/1/82
48 bool foundend, cango, canstop, foundlow;
49 unsigned int i, count200, badcount, nummin, nummax, diff;
52 int valbuf[HAND_SZ], count[NUM_CARDS];
55 wmove(Score, ERR_Y, ERR_X); /* get rid of error messages */
64 /* Try for a Coup Forre, and see what we have. */
65 for (i = 0; i < NUM_CARDS; i++)
67 for (i = 0; i < HAND_SZ; i++) {
70 case C_STOP: case C_CRASH:
71 case C_FLAT: case C_EMPTY:
72 if ((playit[i] = canplay(pp, op, card)) != 0)
76 if ((playit[i] = canplay(pp, op, card))
77 && Numseen[C_25] == Numcards[C_25]
78 && Numseen[C_50] == Numcards[C_50])
81 case C_25: case C_50: case C_75:
82 case C_100: case C_200:
83 if ((playit[i] = canplay(pp, op, card))
84 && pp->mileage + Value[card] == End)
88 playit[i] = canplay(pp, op, card);
93 case C_GAS_SAFE: case C_DRIVE_SAFE:
94 case C_SPARE_SAFE: case C_RIGHT_WAY:
95 if (pp->battle == opposite(card) ||
96 (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
109 /* No Coup Forre. Draw to fill hand, then restart, as needed. */
110 if (pp->hand[0] == C_INIT && Topcard > Deck) {
117 fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
118 cango, canstop, safe);
121 foundend = !check_ext(TRUE);
122 for (i = 0; safe && i < HAND_SZ; i++) {
123 if (issafety(pp->hand[i])) {
124 if (onecard(op) || (foundend && cango && !canstop)) {
128 "CALCMOVE: onecard(op) = %d, foundend = %d\n",
129 onecard(op), foundend);
136 oppos = opposite(pp->hand[i]);
137 if (Numseen[oppos] == Numcards[oppos] &&
138 !(pp->hand[i] == C_RIGHT_WAY &&
139 Numseen[C_LIMIT] != Numcards[C_LIMIT]))
142 && (op->can_go || !pp->can_go || Topcard < Deck)) {
143 card = (Topcard - Deck) - roll(1, 10);
144 if ((!pp->mileage) != (!op->mileage))
149 "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
152 if (card < DECK_SZ / 4)
159 if (!pp->can_go && !isrepair(pp->battle))
160 Numneed[opposite(pp->battle)]++;
162 foundlow = (cango || count[C_END_LIMIT] != 0
163 || Numseen[C_LIMIT] == Numcards[C_LIMIT]
164 || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
166 count200 = pp->nummiles[C_200];
173 for (i = 0; i < HAND_SZ; i++) {
175 if (issafety(card) || playit[i] == (cango != 0)) {
178 fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
182 case C_25: case C_50:
183 diff = End - pp->mileage;
184 /* avoid getting too close */
185 if (Topcard > Deck && cango && diff <= 100
186 && (int)diff / Value[card] > count[card]
187 && (card == C_25 || diff % 50 == 0)) {
188 if (card == C_50 && diff - 50 == 25
197 *value = (Value[card] >> 3);
198 if (pp->speed == C_LIMIT)
203 && (card == C_50 || count[C_50] == 0)) {
204 *value = (pp->mileage ? 10 : 20);
209 if (++count200 > 2) {
213 case C_75: case C_100:
214 *value = (Value[card] >> 3);
215 if (pp->speed == C_LIMIT)
220 if (pp->mileage + Value[card] > End)
221 *value = (End == 700 ? card : 0);
222 else if (pp->mileage + Value[card] == End) {
223 *value = (foundend ? card : V_VALUABLE);
228 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
229 *value = (pp->safety[S_RIGHT_WAY] ==
231 else if (pp->speed == C_LIMIT &&
232 End - pp->mileage <= 50)
234 else if (pp->speed == C_LIMIT
235 || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
242 --count[C_END_LIMIT];
245 case C_REPAIRS: case C_SPARE: case C_GAS:
246 safe = safety(card) - S_CONV;
247 oppos = opposite(card);
248 if (pp->safety[safe] != S_UNKNOWN)
249 *value = (pp->safety[safe] ==
251 else if (pp->battle != oppos
252 && (Numseen[oppos] == Numcards[oppos] ||
253 Numseen[oppos] + count[card] >
260 *value = Numcards[oppos] * 6;
261 *value += Numseen[card] -
264 *value /= (count[card]*count[card]);
269 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
270 *value = (pp->safety[S_RIGHT_WAY] ==
273 && Numgos + count[C_GO] == Numneed[C_GO]) {
278 *value = Numneed[C_GO] * 3;
279 *value += (Numseen[C_GO] - Numgos);
280 *value /= (count[C_GO] * count[C_GO]);
285 if (op->mileage + 50 >= End) {
286 *value = (End == 700 && !cango);
289 if (canstop || (cango && !op->can_go))
292 *value = (pp->safety[S_RIGHT_WAY] !=
299 case C_CRASH: case C_EMPTY: case C_FLAT:
300 safe = safety(card) - S_CONV;
301 oppos = opposite(card);
302 *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
304 if (op->safety[safe] == S_PLAYED)
307 *value *= Numneed[oppos] +
309 if (!pp->mileage || foundend ||
312 if (op->mileage == 0 || onecard(op))
314 if (op->speed == C_LIMIT)
317 pp->safety[safe] != S_UNKNOWN)
320 *value /= ++badcount;
324 if (op->safety[S_RIGHT_WAY] == S_PLAYED)
327 *value = (pp->safety[S_RIGHT_WAY] !=
329 *value *= Numcards[C_STOP] +
331 if (!pp->mileage || foundend ||
335 *value /= ++badcount;
336 if (op->mileage == 0)
338 if ((card == C_LIMIT &&
339 op->speed == C_LIMIT) ||
342 if (cango && pp->safety[S_RIGHT_WAY] !=
347 case C_GAS_SAFE: case C_DRIVE_SAFE:
348 case C_SPARE_SAFE: case C_RIGHT_WAY:
349 *value = cango ? 0 : 101;
357 *value = cango ? 0 : 101;
358 if (card != C_INIT) {
359 if (*value >= curmax) {
363 if (*value <= curmin) {
370 mvprintw(i + 6, 2, "%3d %-14s", *value,
371 C_name[pp->hand[i]]);
375 if (!pp->can_go && !isrepair(pp->battle))
376 Numneed[opposite(pp->battle)]++;
379 mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
384 if (issafety(pp->hand[nummin])) { /* NEVER discard a safety */
388 mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
389 Movetype = M_DISCARD;
392 mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
396 * Return true if the given player could conceivably win with his next card.
406 if (pp->can_go || ((isrepair(bat) || bat == C_STOP || spd == C_LIMIT) &&
407 Numseen[S_RIGHT_WAY] != 0) ||
408 (bat >= 0 && Numseen[safety(bat)] != 0))
409 switch (End - pp->mileage) {
411 if (pp->nummiles[C_200] == 2)
418 card = (End - pp->mileage == 75 ? C_75 : C_100);
420 return Numseen[S_RIGHT_WAY] == 0;
424 card = (End - pp->mileage == 25 ? C_25 : C_50);
425 return Numseen[card] != Numcards[card];
431 canplay(PLAY *pp, PLAY *op, CARD card)
435 if (pp->nummiles[C_200] == 2)
438 case C_75: case C_100:
439 if (pp->speed == C_LIMIT)
443 if (pp->mileage + Value[card] > End)
450 case C_EMPTY: case C_FLAT: case C_CRASH:
452 if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
456 if (op->speed != C_LIMIT &&
457 op->safety[S_RIGHT_WAY] != S_PLAYED &&
458 op->mileage + 50 < End)
461 case C_GAS: case C_SPARE: case C_REPAIRS:
462 if (pp->battle == opposite(card))
467 (isrepair(pp->battle) || pp->battle == C_STOP))
471 if (pp->speed == C_LIMIT)