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