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