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