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