fixes for ANSI C
[unix-history] / usr / src / games / mille / move.c
CommitLineData
d6207a92
KB
1/*
2 * Copyright (c) 1983 Regents of the University of California.
792d102c
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
65c7d3b6
KB
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.
d6207a92
KB
16 */
17
18#ifndef lint
65c7d3b6 19static char sccsid[] = "@(#)move.c 5.3 (Berkeley) %G%";
792d102c 20#endif /* not lint */
d6207a92
KB
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
39char *Movenames[] = {
40 "M_DISCARD", "M_DRAW", "M_PLAY", "M_ORDER"
41 };
42
43domove()
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;
792d102c 91#ifdef DEBUG
d6207a92
KB
92 if (Debug)
93 fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]);
792d102c 94#endif
d6207a92
KB
95acc:
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;
792d102c 104#ifdef DEBUG
d6207a92
KB
105 if (Debug)
106 fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]);
792d102c 107#endif
d6207a92
KB
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 */
146check_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)) {
792d102c 157#ifdef DEBUG
d6207a92
KB
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 }
792d102c 163#endif
d6207a92
KB
164 return;
165 }
792d102c 166#ifdef DEBUG
d6207a92
KB
167 else if (Debug)
168 fprintf(outf, "CHECK_GO: cannot play %s\n",
169 C_name[card]);
792d102c 170#endif
d6207a92
KB
171 }
172 }
173 Finished = TRUE;
174}
175
176playcard(pp)
177reg 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))
188mustpick:
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];
792d102c 196#ifdef DEBUG
d6207a92
KB
197 if (Debug)
198 fprintf(outf, "PLAYCARD: Card = %s\n", C_name[card]);
792d102c 199#endif
d6207a92
KB
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)
251protected:
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
325getmove()
326{
327 reg char c, *sp;
d6207a92
KB
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;
792d102c 409#ifdef DEBUG
d6207a92 410 case 'Z': /* Debug code */
792d102c
KB
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();
d6207a92 429 }
d6207a92 430 }
792d102c
KB
431 else
432 addstr(unctrl(*sp++));
433 refresh();
d6207a92 434 }
792d102c
KB
435 *sp = '\0';
436 leaveok(Board, TRUE);
437 if ((outf = fopen(buf, "w")) == NULL)
438 perror(buf);
439 setbuf(outf, (char *)NULL);
d6207a92 440 }
792d102c
KB
441 Debug = !Debug;
442 break;
443#endif
d6207a92
KB
444 default:
445 error("unknown command: %s", unctrl(c));
446 break;
447 }
448 }
449ret:
450 leaveok(Board, TRUE);
451}
452/*
453 * return whether or not the player has picked
454 */
455haspicked(pp)
456reg 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
474account(card)
475reg 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
499prompt(promptno)
500int 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
530sort(hand)
531reg 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