|
|
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.