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