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