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