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