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