|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 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[] = "@(#)move.c 5.3 (Berkeley) 6/18/88"; ! 20: #endif /* not lint */ ! 21: ! 22: #include "mille.h" ! 23: #ifndef unctrl ! 24: #include "unctrl.h" ! 25: #endif ! 26: ! 27: # ifdef attron ! 28: # include <term.h> ! 29: # define _tty cur_term->Nttyb ! 30: # endif attron ! 31: ! 32: /* ! 33: * @(#)move.c 1.2 (Berkeley) 3/28/83 ! 34: */ ! 35: ! 36: #undef CTRL ! 37: #define CTRL(c) (c - 'A' + 1) ! 38: ! 39: char *Movenames[] = { ! 40: "M_DISCARD", "M_DRAW", "M_PLAY", "M_ORDER" ! 41: }; ! 42: ! 43: domove() ! 44: { ! 45: reg PLAY *pp; ! 46: reg int i, j; ! 47: reg bool goodplay; ! 48: ! 49: pp = &Player[Play]; ! 50: if (Play == PLAYER) ! 51: getmove(); ! 52: else ! 53: calcmove(); ! 54: Next = FALSE; ! 55: goodplay = TRUE; ! 56: switch (Movetype) { ! 57: case M_DISCARD: ! 58: if (haspicked(pp)) { ! 59: if (pp->hand[Card_no] == C_INIT) ! 60: if (Card_no == 6) ! 61: Finished = TRUE; ! 62: else ! 63: error("no card there"); ! 64: else { ! 65: if (issafety(pp->hand[Card_no])) { ! 66: error("discard a safety?"); ! 67: goodplay = FALSE; ! 68: break; ! 69: } ! 70: Discard = pp->hand[Card_no]; ! 71: pp->hand[Card_no] = C_INIT; ! 72: Next = TRUE; ! 73: if (Play == PLAYER) ! 74: account(Discard); ! 75: } ! 76: } ! 77: else ! 78: error("must pick first"); ! 79: break; ! 80: case M_PLAY: ! 81: goodplay = playcard(pp); ! 82: break; ! 83: case M_DRAW: ! 84: Card_no = 0; ! 85: if (Topcard <= Deck) ! 86: error("no more cards"); ! 87: else if (haspicked(pp)) ! 88: error("already picked"); ! 89: else { ! 90: pp->hand[0] = *--Topcard; ! 91: #ifdef DEBUG ! 92: if (Debug) ! 93: fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]); ! 94: #endif ! 95: acc: ! 96: if (Play == COMP) { ! 97: account(*Topcard); ! 98: if (issafety(*Topcard)) ! 99: pp->safety[*Topcard-S_CONV] = S_IN_HAND; ! 100: } ! 101: if (pp->hand[1] == C_INIT && Topcard > Deck) { ! 102: Card_no = 1; ! 103: pp->hand[1] = *--Topcard; ! 104: #ifdef DEBUG ! 105: if (Debug) ! 106: fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]); ! 107: #endif ! 108: goto acc; ! 109: } ! 110: pp->new_battle = FALSE; ! 111: pp->new_speed = FALSE; ! 112: } ! 113: break; ! 114: ! 115: case M_ORDER: ! 116: break; ! 117: } ! 118: /* ! 119: * move blank card to top by one of two methods. If the ! 120: * computer's hand was sorted, the randomness for picking ! 121: * between equally valued cards would be lost ! 122: */ ! 123: if (Order && Movetype != M_DRAW && goodplay && pp == &Player[PLAYER]) ! 124: sort(pp->hand); ! 125: else ! 126: for (i = 1; i < HAND_SZ; i++) ! 127: if (pp->hand[i] == C_INIT) { ! 128: for (j = 0; pp->hand[j] == C_INIT; j++) ! 129: if (j >= HAND_SZ) { ! 130: j = 0; ! 131: break; ! 132: } ! 133: pp->hand[i] = pp->hand[j]; ! 134: pp->hand[j] = C_INIT; ! 135: } ! 136: if (Topcard <= Deck) ! 137: check_go(); ! 138: if (Next) ! 139: nextplay(); ! 140: } ! 141: ! 142: /* ! 143: * Check and see if either side can go. If they cannot, ! 144: * the game is over ! 145: */ ! 146: check_go() { ! 147: ! 148: reg CARD card; ! 149: reg PLAY *pp, *op; ! 150: reg int i; ! 151: ! 152: for (pp = Player; pp < &Player[2]; pp++) { ! 153: op = (pp == &Player[COMP] ? &Player[PLAYER] : &Player[COMP]); ! 154: for (i = 0; i < HAND_SZ; i++) { ! 155: card = pp->hand[i]; ! 156: if (issafety(card) || canplay(pp, op, card)) { ! 157: #ifdef DEBUG ! 158: if (Debug) { ! 159: fprintf(outf, "CHECK_GO: can play %s (%d), ", C_name[card], card); ! 160: fprintf(outf, "issafety(card) = %d, ", issafety(card)); ! 161: fprintf(outf, "canplay(pp, op, card) = %d\n", canplay(pp, op, card)); ! 162: } ! 163: #endif ! 164: return; ! 165: } ! 166: #ifdef DEBUG ! 167: else if (Debug) ! 168: fprintf(outf, "CHECK_GO: cannot play %s\n", ! 169: C_name[card]); ! 170: #endif ! 171: } ! 172: } ! 173: Finished = TRUE; ! 174: } ! 175: ! 176: playcard(pp) ! 177: reg PLAY *pp; ! 178: { ! 179: reg int v; ! 180: reg CARD card; ! 181: ! 182: /* ! 183: * check and see if player has picked ! 184: */ ! 185: switch (pp->hand[Card_no]) { ! 186: default: ! 187: if (!haspicked(pp)) ! 188: mustpick: ! 189: return error("must pick first"); ! 190: case C_GAS_SAFE: case C_SPARE_SAFE: ! 191: case C_DRIVE_SAFE: case C_RIGHT_WAY: ! 192: break; ! 193: } ! 194: ! 195: card = pp->hand[Card_no]; ! 196: #ifdef DEBUG ! 197: if (Debug) ! 198: fprintf(outf, "PLAYCARD: Card = %s\n", C_name[card]); ! 199: #endif ! 200: Next = FALSE; ! 201: switch (card) { ! 202: case C_200: ! 203: if (pp->nummiles[C_200] == 2) ! 204: return error("only two 200's per hand"); ! 205: case C_100: case C_75: ! 206: if (pp->speed == C_LIMIT) ! 207: return error("limit of 50"); ! 208: case C_50: ! 209: if (pp->mileage + Value[card] > End) ! 210: return error("puts you over %d", End); ! 211: case C_25: ! 212: if (!pp->can_go) ! 213: return error("cannot move now"); ! 214: pp->nummiles[card]++; ! 215: v = Value[card]; ! 216: pp->total += v; ! 217: pp->hand_tot += v; ! 218: if ((pp->mileage += v) == End) ! 219: check_ext(FALSE); ! 220: break; ! 221: ! 222: case C_GAS: case C_SPARE: case C_REPAIRS: ! 223: if (pp->battle != opposite(card)) ! 224: return error("can't play \"%s\"", C_name[card]); ! 225: pp->battle = card; ! 226: if (pp->safety[S_RIGHT_WAY] == S_PLAYED) ! 227: pp->can_go = TRUE; ! 228: break; ! 229: ! 230: case C_GO: ! 231: if (pp->battle != C_INIT && pp->battle != C_STOP ! 232: && !isrepair(pp->battle)) ! 233: return error("cannot play \"Go\" on a \"%s\"", ! 234: C_name[pp->battle]); ! 235: pp->battle = C_GO; ! 236: pp->can_go = TRUE; ! 237: break; ! 238: ! 239: case C_END_LIMIT: ! 240: if (pp->speed != C_LIMIT) ! 241: return error("not limited"); ! 242: pp->speed = C_END_LIMIT; ! 243: break; ! 244: ! 245: case C_EMPTY: case C_FLAT: case C_CRASH: ! 246: case C_STOP: ! 247: pp = &Player[other(Play)]; ! 248: if (!pp->can_go) ! 249: return error("opponent cannot go"); ! 250: else if (pp->safety[safety(card) - S_CONV] == S_PLAYED) ! 251: protected: ! 252: return error("opponent is protected"); ! 253: pp->battle = card; ! 254: pp->new_battle = TRUE; ! 255: pp->can_go = FALSE; ! 256: pp = &Player[Play]; ! 257: break; ! 258: ! 259: case C_LIMIT: ! 260: pp = &Player[other(Play)]; ! 261: if (pp->speed == C_LIMIT) ! 262: return error("opponent has limit"); ! 263: if (pp->safety[S_RIGHT_WAY] == S_PLAYED) ! 264: goto protected; ! 265: pp->speed = C_LIMIT; ! 266: pp->new_speed = TRUE; ! 267: pp = &Player[Play]; ! 268: break; ! 269: ! 270: case C_GAS_SAFE: case C_SPARE_SAFE: ! 271: case C_DRIVE_SAFE: case C_RIGHT_WAY: ! 272: if (pp->battle == opposite(card) ! 273: || (card == C_RIGHT_WAY && pp->speed == C_LIMIT)) { ! 274: if (!(card == C_RIGHT_WAY && !isrepair(pp->battle))) { ! 275: pp->battle = C_GO; ! 276: pp->can_go = TRUE; ! 277: } ! 278: if (card == C_RIGHT_WAY && pp->speed == C_LIMIT) ! 279: pp->speed = C_INIT; ! 280: if (pp->new_battle ! 281: || (pp->new_speed && card == C_RIGHT_WAY)) { ! 282: pp->coups[card - S_CONV] = TRUE; ! 283: pp->total += SC_COUP; ! 284: pp->hand_tot += SC_COUP; ! 285: pp->coupscore += SC_COUP; ! 286: } ! 287: } ! 288: /* ! 289: * if not coup, must pick first ! 290: */ ! 291: else if (pp->hand[0] == C_INIT && Topcard > Deck) ! 292: goto mustpick; ! 293: pp->safety[card - S_CONV] = S_PLAYED; ! 294: pp->total += SC_SAFETY; ! 295: pp->hand_tot += SC_SAFETY; ! 296: if ((pp->safescore += SC_SAFETY) == NUM_SAFE * SC_SAFETY) { ! 297: pp->total += SC_ALL_SAFE; ! 298: pp->hand_tot += SC_ALL_SAFE; ! 299: } ! 300: if (card == C_RIGHT_WAY) { ! 301: if (pp->speed == C_LIMIT) ! 302: pp->speed = C_INIT; ! 303: if (pp->battle == C_STOP || pp->battle == C_INIT) { ! 304: pp->can_go = TRUE; ! 305: pp->battle = C_INIT; ! 306: } ! 307: if (!pp->can_go && isrepair(pp->battle)) ! 308: pp->can_go = TRUE; ! 309: } ! 310: Next = -1; ! 311: break; ! 312: ! 313: case C_INIT: ! 314: error("no card there"); ! 315: Next = -1; ! 316: break; ! 317: } ! 318: if (pp == &Player[PLAYER]) ! 319: account(card); ! 320: pp->hand[Card_no] = C_INIT; ! 321: Next = (Next == -1 ? FALSE : TRUE); ! 322: return TRUE; ! 323: } ! 324: ! 325: getmove() ! 326: { ! 327: reg char c, *sp; ! 328: #ifdef EXTRAP ! 329: static bool last_ex = FALSE; /* set if last command was E */ ! 330: ! 331: if (last_ex) { ! 332: undoex(); ! 333: prboard(); ! 334: last_ex = FALSE; ! 335: } ! 336: #endif ! 337: for (;;) { ! 338: prompt(MOVEPROMPT); ! 339: leaveok(Board, FALSE); ! 340: refresh(); ! 341: while ((c = readch()) == killchar() || c == erasechar()) ! 342: continue; ! 343: if (islower(c)) ! 344: c = toupper(c); ! 345: if (isprint(c) && !isspace(c)) { ! 346: addch(c); ! 347: refresh(); ! 348: } ! 349: switch (c) { ! 350: case 'P': /* Pick */ ! 351: Movetype = M_DRAW; ! 352: goto ret; ! 353: case 'U': /* Use Card */ ! 354: case 'D': /* Discard Card */ ! 355: if ((Card_no = getcard()) < 0) ! 356: break; ! 357: Movetype = (c == 'U' ? M_PLAY : M_DISCARD); ! 358: goto ret; ! 359: case 'O': /* Order */ ! 360: Order = !Order; ! 361: if (Window == W_SMALL) { ! 362: if (!Order) ! 363: mvwaddstr(Score, 12, 21, ! 364: "o: order hand"); ! 365: else ! 366: mvwaddstr(Score, 12, 21, ! 367: "o: stop ordering"); ! 368: wclrtoeol(Score); ! 369: } ! 370: Movetype = M_ORDER; ! 371: goto ret; ! 372: case 'Q': /* Quit */ ! 373: rub(); /* Same as a rubout */ ! 374: break; ! 375: case 'W': /* Window toggle */ ! 376: Window = nextwin(Window); ! 377: newscore(); ! 378: prscore(TRUE); ! 379: wrefresh(Score); ! 380: break; ! 381: case 'R': /* Redraw screen */ ! 382: case CTRL('L'): ! 383: wrefresh(curscr); ! 384: break; ! 385: case 'S': /* Save game */ ! 386: On_exit = FALSE; ! 387: save(); ! 388: break; ! 389: case 'E': /* Extrapolate */ ! 390: #ifdef EXTRAP ! 391: if (last_ex) ! 392: break; ! 393: Finished = TRUE; ! 394: if (Window != W_FULL) ! 395: newscore(); ! 396: prscore(FALSE); ! 397: wrefresh(Score); ! 398: last_ex = TRUE; ! 399: Finished = FALSE; ! 400: #else ! 401: error("%c: command not implemented", c); ! 402: #endif ! 403: break; ! 404: case '\r': /* Ignore RETURNs and */ ! 405: case '\n': /* Line Feeds */ ! 406: case ' ': /* Spaces */ ! 407: case '\0': /* and nulls */ ! 408: break; ! 409: #ifdef DEBUG ! 410: case 'Z': /* Debug code */ ! 411: if (!Debug && outf == NULL) { ! 412: char buf[MAXPATHLEN]; ! 413: ! 414: prompt(FILEPROMPT); ! 415: leaveok(Board, FALSE); ! 416: refresh(); ! 417: sp = buf; ! 418: while ((*sp = readch()) != '\n') { ! 419: if (*sp == killchar()) ! 420: goto over; ! 421: else if (*sp == erasechar()) { ! 422: if (--sp < buf) ! 423: sp = buf; ! 424: else { ! 425: addch('\b'); ! 426: if (*sp < ' ') ! 427: addch('\b'); ! 428: clrtoeol(); ! 429: } ! 430: } ! 431: else ! 432: addstr(unctrl(*sp++)); ! 433: refresh(); ! 434: } ! 435: *sp = '\0'; ! 436: leaveok(Board, TRUE); ! 437: if ((outf = fopen(buf, "w")) == NULL) ! 438: perror(buf); ! 439: setbuf(outf, (char *)NULL); ! 440: } ! 441: Debug = !Debug; ! 442: break; ! 443: #endif ! 444: default: ! 445: error("unknown command: %s", unctrl(c)); ! 446: break; ! 447: } ! 448: } ! 449: ret: ! 450: leaveok(Board, TRUE); ! 451: } ! 452: /* ! 453: * return whether or not the player has picked ! 454: */ ! 455: haspicked(pp) ! 456: reg PLAY *pp; { ! 457: ! 458: reg int card; ! 459: ! 460: if (Topcard <= Deck) ! 461: return TRUE; ! 462: switch (pp->hand[Card_no]) { ! 463: case C_GAS_SAFE: case C_SPARE_SAFE: ! 464: case C_DRIVE_SAFE: case C_RIGHT_WAY: ! 465: card = 1; ! 466: break; ! 467: default: ! 468: card = 0; ! 469: break; ! 470: } ! 471: return (pp->hand[card] != C_INIT); ! 472: } ! 473: ! 474: account(card) ! 475: reg CARD card; { ! 476: ! 477: reg CARD oppos; ! 478: ! 479: if (card == C_INIT) ! 480: return; ! 481: ++Numseen[card]; ! 482: if (Play == COMP) ! 483: switch (card) { ! 484: case C_GAS_SAFE: ! 485: case C_SPARE_SAFE: ! 486: case C_DRIVE_SAFE: ! 487: oppos = opposite(card); ! 488: Numgos += Numcards[oppos] - Numseen[oppos]; ! 489: break; ! 490: case C_CRASH: ! 491: case C_FLAT: ! 492: case C_EMPTY: ! 493: case C_STOP: ! 494: Numgos++; ! 495: break; ! 496: } ! 497: } ! 498: ! 499: prompt(promptno) ! 500: int promptno; ! 501: { ! 502: static char *names[] = { ! 503: ">>:Move:", ! 504: "Really?", ! 505: "Another hand?", ! 506: "Another game?", ! 507: "Save game?", ! 508: "Same file?", ! 509: "file:", ! 510: "Extension?", ! 511: "Overwrite file?", ! 512: }; ! 513: static int last_prompt = -1; ! 514: ! 515: if (promptno == last_prompt) ! 516: move(MOVE_Y, MOVE_X + strlen(names[promptno]) + 1); ! 517: else { ! 518: move(MOVE_Y, MOVE_X); ! 519: if (promptno == MOVEPROMPT) ! 520: standout(); ! 521: addstr(names[promptno]); ! 522: if (promptno == MOVEPROMPT) ! 523: standend(); ! 524: addch(' '); ! 525: last_prompt = promptno; ! 526: } ! 527: clrtoeol(); ! 528: } ! 529: ! 530: sort(hand) ! 531: reg CARD *hand; ! 532: { ! 533: reg CARD *cp, *tp; ! 534: reg CARD temp; ! 535: ! 536: cp = hand; ! 537: hand += HAND_SZ; ! 538: for ( ; cp < &hand[-1]; cp++) ! 539: for (tp = cp + 1; tp < hand; tp++) ! 540: if (*cp > *tp) { ! 541: temp = *cp; ! 542: *cp = *tp; ! 543: *tp = temp; ! 544: } ! 545: } ! 546:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.