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