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