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