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