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