xref: /openbsd-src/games/mille/move.c (revision 56f9a7dc4a81dac179f24a870e2e9dfb2615d6c2)
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