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