]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - mille/comp.c
WARNSify
[bsdgames-darwin.git] / mille / comp.c
1 /* $NetBSD: comp.c,v 1.5 1997/10/12 00:53:45 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)comp.c 8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: comp.c,v 1.5 1997/10/12 00:53:45 lukem Exp $");
42 #endif
43 #endif /* not lint */
44
45 # include "mille.h"
46
47 /*
48 * @(#)comp.c 1.1 (Berkeley) 4/1/82
49 */
50
51 # define V_VALUABLE 40
52
53 void
54 calcmove()
55 {
56 CARD card;
57 int *value;
58 PLAY *pp, *op;
59 bool foundend, cango, canstop, foundlow;
60 unsgn int i, count200, badcount, nummin, nummax, diff;
61 int curmin, curmax;
62 CARD safe, oppos;
63 int valbuf[HAND_SZ], count[NUM_CARDS];
64 bool playit[HAND_SZ];
65
66 wmove(Score, ERR_Y, ERR_X); /* get rid of error messages */
67 wclrtoeol(Score);
68 pp = &Player[COMP];
69 op = &Player[PLAYER];
70 safe = 0;
71 cango = 0;
72 canstop = FALSE;
73 foundend = FALSE;
74
75 /* Try for a Coup Forre, and see what we have. */
76 for (i = 0; i < NUM_CARDS; i++)
77 count[i] = 0;
78 for (i = 0; i < HAND_SZ; i++) {
79 card = pp->hand[i];
80 switch (card) {
81 case C_STOP: case C_CRASH:
82 case C_FLAT: case C_EMPTY:
83 if ((playit[i] = canplay(pp, op, card)) != 0)
84 canstop = TRUE;
85 goto norm;
86 case C_LIMIT:
87 if ((playit[i] = canplay(pp, op, card))
88 && Numseen[C_25] == Numcards[C_25]
89 && Numseen[C_50] == Numcards[C_50])
90 canstop = TRUE;
91 goto norm;
92 case C_25: case C_50: case C_75:
93 case C_100: case C_200:
94 if ((playit[i] = canplay(pp, op, card))
95 && pp->mileage + Value[card] == End)
96 foundend = TRUE;
97 goto norm;
98 default:
99 playit[i] = canplay(pp, op, card);
100 norm:
101 if (playit[i])
102 ++cango;
103 break;
104 case C_GAS_SAFE: case C_DRIVE_SAFE:
105 case C_SPARE_SAFE: case C_RIGHT_WAY:
106 if (pp->battle == opposite(card) ||
107 (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
108 Movetype = M_PLAY;
109 Card_no = i;
110 return;
111 }
112 ++safe;
113 playit[i] = TRUE;
114 break;
115 }
116 if (card >= 0)
117 ++count[card];
118 }
119
120 /* No Coup Forre. Draw to fill hand, then restart, as needed. */
121 if (pp->hand[0] == C_INIT && Topcard > Deck) {
122 Movetype = M_DRAW;
123 return;
124 }
125
126 #ifdef DEBUG
127 if (Debug)
128 fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
129 cango, canstop, safe);
130 #endif
131 if (foundend)
132 foundend = !check_ext(TRUE);
133 for (i = 0; safe && i < HAND_SZ; i++) {
134 if (issafety(pp->hand[i])) {
135 if (onecard(op) || (foundend && cango && !canstop)) {
136 #ifdef DEBUG
137 if (Debug)
138 fprintf(outf,
139 "CALCMOVE: onecard(op) = %d, foundend = %d\n",
140 onecard(op), foundend);
141 #endif
142 playsafe:
143 Movetype = M_PLAY;
144 Card_no = i;
145 return;
146 }
147 oppos = opposite(pp->hand[i]);
148 if (Numseen[oppos] == Numcards[oppos] &&
149 !(pp->hand[i] == C_RIGHT_WAY &&
150 Numseen[C_LIMIT] != Numcards[C_LIMIT]))
151 goto playsafe;
152 else if (!cango
153 && (op->can_go || !pp->can_go || Topcard < Deck)) {
154 card = (Topcard - Deck) - roll(1, 10);
155 if ((!pp->mileage) != (!op->mileage))
156 card -= 7;
157 #ifdef DEBUG
158 if (Debug)
159 fprintf(outf,
160 "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
161 card, DECK_SZ / 4);
162 #endif
163 if (card < DECK_SZ / 4)
164 goto playsafe;
165 }
166 safe--;
167 playit[i] = cango;
168 }
169 }
170 if (!pp->can_go && !isrepair(pp->battle))
171 Numneed[opposite(pp->battle)]++;
172 redoit:
173 foundlow = (cango || count[C_END_LIMIT] != 0
174 || Numseen[C_LIMIT] == Numcards[C_LIMIT]
175 || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
176 foundend = FALSE;
177 count200 = pp->nummiles[C_200];
178 badcount = 0;
179 curmax = -1;
180 curmin = 101;
181 nummin = -1;
182 nummax = -1;
183 value = valbuf;
184 for (i = 0; i < HAND_SZ; i++) {
185 card = pp->hand[i];
186 if (issafety(card) || playit[i] == (cango != 0)) {
187 #ifdef DEBUG
188 if (Debug)
189 fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
190 C_name[card]);
191 #endif
192 switch (card) {
193 case C_25: case C_50:
194 diff = End - pp->mileage;
195 /* avoid getting too close */
196 if (Topcard > Deck && cango && diff <= 100
197 && diff / Value[card] > count[card]
198 && (card == C_25 || diff % 50 == 0)) {
199 if (card == C_50 && diff - 50 == 25
200 && count[C_25] > 0)
201 goto okay;
202 *value = 0;
203 if (--cango <= 0)
204 goto redoit;
205 break;
206 }
207 okay:
208 *value = (Value[card] >> 3);
209 if (pp->speed == C_LIMIT)
210 ++*value;
211 else
212 --*value;
213 if (!foundlow
214 && (card == C_50 || count[C_50] == 0)) {
215 *value = (pp->mileage ? 10 : 20);
216 foundlow = TRUE;
217 }
218 goto miles;
219 case C_200:
220 if (++count200 > 2) {
221 *value = 0;
222 break;
223 }
224 case C_75: case C_100:
225 *value = (Value[card] >> 3);
226 if (pp->speed == C_LIMIT)
227 --*value;
228 else
229 ++*value;
230 miles:
231 if (pp->mileage + Value[card] > End)
232 *value = (End == 700 ? card : 0);
233 else if (pp->mileage + Value[card] == End) {
234 *value = (foundend ? card : V_VALUABLE);
235 foundend = TRUE;
236 }
237 break;
238 case C_END_LIMIT:
239 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
240 *value = (pp->safety[S_RIGHT_WAY] ==
241 S_PLAYED ? -1 : 1);
242 else if (pp->speed == C_LIMIT &&
243 End - pp->mileage <= 50)
244 *value = 1;
245 else if (pp->speed == C_LIMIT
246 || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
247 safe = S_RIGHT_WAY;
248 oppos = C_LIMIT;
249 goto repair;
250 }
251 else {
252 *value = 0;
253 --count[C_END_LIMIT];
254 }
255 break;
256 case C_REPAIRS: case C_SPARE: case C_GAS:
257 safe = safety(card) - S_CONV;
258 oppos = opposite(card);
259 if (pp->safety[safe] != S_UNKNOWN)
260 *value = (pp->safety[safe] ==
261 S_PLAYED ? -1 : 1);
262 else if (pp->battle != oppos
263 && (Numseen[oppos] == Numcards[oppos] ||
264 Numseen[oppos] + count[card] >
265 Numcards[oppos])) {
266 *value = 0;
267 --count[card];
268 }
269 else {
270 repair:
271 *value = Numcards[oppos] * 6;
272 *value += Numseen[card] -
273 Numseen[oppos];
274 if (!cango)
275 *value /= (count[card]*count[card]);
276 count[card]--;
277 }
278 break;
279 case C_GO:
280 if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
281 *value = (pp->safety[S_RIGHT_WAY] ==
282 S_PLAYED ? -1 : 2);
283 else if (pp->can_go
284 && Numgos + count[C_GO] == Numneed[C_GO]) {
285 *value = 0;
286 --count[C_GO];
287 }
288 else {
289 *value = Numneed[C_GO] * 3;
290 *value += (Numseen[C_GO] - Numgos);
291 *value /= (count[C_GO] * count[C_GO]);
292 count[C_GO]--;
293 }
294 break;
295 case C_LIMIT:
296 if (op->mileage + 50 >= End) {
297 *value = (End == 700 && !cango);
298 break;
299 }
300 if (canstop || (cango && !op->can_go))
301 *value = 1;
302 else {
303 *value = (pp->safety[S_RIGHT_WAY] !=
304 S_UNKNOWN ? 2 : 3);
305 safe = S_RIGHT_WAY;
306 oppos = C_END_LIMIT;
307 goto normbad;
308 }
309 break;
310 case C_CRASH: case C_EMPTY: case C_FLAT:
311 safe = safety(card) - S_CONV;
312 oppos = opposite(card);
313 *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
314 normbad:
315 if (op->safety[safe] == S_PLAYED)
316 *value = -1;
317 else {
318 *value *= Numneed[oppos] +
319 Numseen[oppos] + 2;
320 if (!pp->mileage || foundend ||
321 onecard(op))
322 *value += 5;
323 if (op->mileage == 0 || onecard(op))
324 *value += 5;
325 if (op->speed == C_LIMIT)
326 *value -= 3;
327 if (cango &&
328 pp->safety[safe] != S_UNKNOWN)
329 *value += 3;
330 if (!cango)
331 *value /= ++badcount;
332 }
333 break;
334 case C_STOP:
335 if (op->safety[S_RIGHT_WAY] == S_PLAYED)
336 *value = -1;
337 else {
338 *value = (pp->safety[S_RIGHT_WAY] !=
339 S_UNKNOWN ? 3 : 4);
340 *value *= Numcards[C_STOP] +
341 Numseen[C_GO];
342 if (!pp->mileage || foundend ||
343 onecard(op))
344 *value += 5;
345 if (!cango)
346 *value /= ++badcount;
347 if (op->mileage == 0)
348 *value += 5;
349 if ((card == C_LIMIT &&
350 op->speed == C_LIMIT) ||
351 !op->can_go)
352 *value -= 5;
353 if (cango && pp->safety[S_RIGHT_WAY] !=
354 S_UNKNOWN)
355 *value += 5;
356 }
357 break;
358 case C_GAS_SAFE: case C_DRIVE_SAFE:
359 case C_SPARE_SAFE: case C_RIGHT_WAY:
360 *value = cango ? 0 : 101;
361 break;
362 case C_INIT:
363 *value = 0;
364 break;
365 }
366 }
367 else
368 *value = cango ? 0 : 101;
369 if (card != C_INIT) {
370 if (*value >= curmax) {
371 nummax = i;
372 curmax = *value;
373 }
374 if (*value <= curmin) {
375 nummin = i;
376 curmin = *value;
377 }
378 }
379 #ifdef DEBUG
380 if (Debug)
381 mvprintw(i + 6, 2, "%3d %-14s", *value,
382 C_name[pp->hand[i]]);
383 #endif
384 value++;
385 }
386 if (!pp->can_go && !isrepair(pp->battle))
387 Numneed[opposite(pp->battle)]++;
388 if (cango) {
389 play_it:
390 mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
391 Movetype = M_PLAY;
392 Card_no = nummax;
393 }
394 else {
395 if (issafety(pp->hand[nummin])) { /* NEVER discard a safety */
396 nummax = nummin;
397 goto play_it;
398 }
399 mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
400 Movetype = M_DISCARD;
401 Card_no = nummin;
402 }
403 mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
404 }
405
406 /*
407 * Return true if the given player could conceivably win with his next card.
408 */
409 int
410 onecard(pp)
411 PLAY *pp;
412 {
413 CARD bat, spd, card;
414
415 bat = pp->battle;
416 spd = pp->speed;
417 card = -1;
418 if (pp->can_go || ((isrepair(bat) || bat == C_STOP || spd == C_LIMIT) &&
419 Numseen[S_RIGHT_WAY] != 0) ||
420 (bat >= 0 && Numseen[safety(bat)] != 0))
421 switch (End - pp->mileage) {
422 case 200:
423 if (pp->nummiles[C_200] == 2)
424 return FALSE;
425 card = C_200;
426 /* FALLTHROUGH */
427 case 100:
428 case 75:
429 if (card == -1)
430 card = (End - pp->mileage == 75 ? C_75 : C_100);
431 if (spd == C_LIMIT)
432 return Numseen[S_RIGHT_WAY] == 0;
433 case 50:
434 case 25:
435 if (card == -1)
436 card = (End - pp->mileage == 25 ? C_25 : C_50);
437 return Numseen[card] != Numcards[card];
438 }
439 return FALSE;
440 }
441
442 int
443 canplay(pp, op, card)
444 PLAY *pp, *op;
445 CARD card;
446 {
447 switch (card) {
448 case C_200:
449 if (pp->nummiles[C_200] == 2)
450 break;
451 /* FALLTHROUGH */
452 case C_75: case C_100:
453 if (pp->speed == C_LIMIT)
454 break;
455 /* FALLTHROUGH */
456 case C_50:
457 if (pp->mileage + Value[card] > End)
458 break;
459 /* FALLTHROUGH */
460 case C_25:
461 if (pp->can_go)
462 return TRUE;
463 break;
464 case C_EMPTY: case C_FLAT: case C_CRASH:
465 case C_STOP:
466 if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
467 return TRUE;
468 break;
469 case C_LIMIT:
470 if (op->speed != C_LIMIT &&
471 op->safety[S_RIGHT_WAY] != S_PLAYED &&
472 op->mileage + 50 < End)
473 return TRUE;
474 break;
475 case C_GAS: case C_SPARE: case C_REPAIRS:
476 if (pp->battle == opposite(card))
477 return TRUE;
478 break;
479 case C_GO:
480 if (!pp->can_go &&
481 (isrepair(pp->battle) || pp->battle == C_STOP))
482 return TRUE;
483 break;
484 case C_END_LIMIT:
485 if (pp->speed == C_LIMIT)
486 return TRUE;
487 }
488 return FALSE;
489 }