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