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