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