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