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