misc.c revision 1.6
1/*	$OpenBSD: misc.c,v 1.6 2000/07/23 21:50:20 pjanzen Exp $	*/
2/*	$NetBSD: misc.c,v 1.4 1995/03/24 05:01:54 cgd Exp $	*/
3
4/*
5 * Copyright (c) 1983, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)misc.c	8.1 (Berkeley) 5/31/93";
40#else
41static char rcsid[] = "$OpenBSD: misc.c,v 1.6 2000/07/23 21:50:20 pjanzen Exp $";
42#endif
43#endif /* not lint */
44
45#include <sys/file.h>
46#include <termios.h>
47
48#if __STDC__
49#include	<stdarg.h>
50#else
51#include	<varargs.h>
52#endif
53
54#include	"mille.h"
55
56/*
57 * @(#)misc.c	1.2 (Berkeley) 3/28/83
58 */
59
60#define	NUMSAFE	4
61
62bool
63#if __STDC__
64error(char *str, ...)
65#else
66error(str, arg)
67	char	*str;
68	va_dcl
69#endif
70{
71	va_list ap;
72
73#if __STDC__
74	va_start(ap, str);
75#else
76	va_start(ap);
77#endif
78	wmove(Score, ERR_Y, ERR_X);
79	vwprintw(Score, str, ap);
80	wclrtoeol(Score);
81	beep();
82	refresh();
83	va_end(ap);
84	return FALSE;
85}
86
87CARD
88getcard()
89{
90	int	c, c1;
91
92	for (;;) {
93		while ((c = readch()) == '\n' || c == '\r' || c == ' ')
94			continue;
95		if (islower(c))
96			c = toupper(c);
97		if (c == killchar() || c == erasechar())
98			return -1;
99		addstr(unctrl(c));
100		clrtoeol();
101		switch (c) {
102		  case '1':	case '2':	case '3':
103		  case '4':	case '5':	case '6':
104			c -= '0';
105			break;
106		  case '0':	case 'P':	case 'p':
107			c = 0;
108			break;
109		  default:
110			putchar('\07');
111			addch('\b');
112			if (!isprint(c))
113				addch('\b');
114			c = -1;
115			break;
116		}
117		refresh();
118		if (c >= 0) {
119			while ((c1 = readch()) != '\r' && c1 != '\n' && c1 != ' ')
120				if (c1 == killchar())
121					return -1;
122				else if (c1 == erasechar()) {
123					addch('\b');
124					clrtoeol();
125					refresh();
126					goto cont;
127				}
128				else
129					write(0, "\07", 1);
130			return c;
131		}
132cont:		;
133	}
134}
135
136int
137check_ext(forcomp)
138	bool	forcomp;
139{
140	if (End == 700) {
141		if (Play == PLAYER) {
142			if (getyn(EXTENSIONPROMPT)) {
143extend:
144				if (!forcomp)
145					End = 1000;
146				return TRUE;
147			} else {
148done:
149				if (!forcomp)
150					Finished = TRUE;
151				return FALSE;
152			}
153		} else {
154			PLAY	*pp, *op;
155			int	i, safe, miles;
156
157			pp = &Player[COMP];
158			op = &Player[PLAYER];
159			for (safe = 0, i = 0; i < NUMSAFE; i++)
160				if (pp->safety[i] != S_UNKNOWN)
161					safe++;
162			if (safe < 2)
163				goto done;
164			if (op->mileage == 0 || onecard(op)
165			    || (op->can_go && op->mileage >= 500))
166				goto done;
167			for (miles = 0, i = 0; i < NUMSAFE; i++)
168				if (op->safety[i] != S_PLAYED
169				    && pp->safety[i] == S_UNKNOWN)
170					miles++;
171			if (miles + safe == NUMSAFE)
172				goto extend;
173			for (miles = 0, i = 0; i < HAND_SZ; i++)
174				if ((safe = pp->hand[i]) <= C_200)
175					miles += Value[safe];
176			if (miles + (Topcard - Deck) * 3 > 1000)
177				goto extend;
178			goto done;
179		}
180	} else
181		goto done;
182}
183
184/*
185 *	Get a yes or no answer to the given question.  Saves are
186 * also allowed.  Return TRUE if the answer was yes, FALSE if no.
187 */
188int
189getyn(promptno)
190	int	promptno;
191{
192	char	c;
193
194	Saved = FALSE;
195	for (;;) {
196		leaveok(Board, FALSE);
197		prompt(promptno);
198		clrtoeol();
199		refresh();
200		switch (c = readch()) {
201		  case 'n':	case 'N':
202			addch('N');
203			refresh();
204			leaveok(Board, TRUE);
205			return FALSE;
206		  case 'y':	case 'Y':
207			addch('Y');
208			refresh();
209			leaveok(Board, TRUE);
210			return TRUE;
211		  case 's':	case 'S':
212			addch('S');
213			refresh();
214			Saved = save();
215			continue;
216		  case CTRL('L'):
217			wrefresh(curscr);
218			break;
219		  default:
220			addstr(unctrl(c));
221			refresh();
222			putchar('\07');
223			break;
224		}
225	}
226}
227
228/*
229 *	Check to see if more games are desired.  If not, and game
230 * came from a saved file, make sure that they don't want to restore
231 * it.  Exit appropriately.
232 */
233void
234check_more()
235{
236	On_exit = TRUE;
237	if (Player[PLAYER].total >= 5000 || Player[COMP].total >= 5000) {
238		if (getyn(ANOTHERGAMEPROMPT))
239			return;
240		else {
241			/*
242			 * must do accounting normally done in main()
243			 */
244			if (Player[PLAYER].total > Player[COMP].total)
245				Player[PLAYER].games++;
246			else if (Player[PLAYER].total < Player[COMP].total)
247				Player[COMP].games++;
248			Player[COMP].total = 0;
249			Player[PLAYER].total = 0;
250		}
251	} else
252		if (getyn(ANOTHERHANDPROMPT))
253			return;
254	if (!Saved && getyn(SAVEGAMEPROMPT))
255		if (!save())
256			return;
257	die(0);
258}
259
260int
261readch()
262{
263	int	cnt;
264	static char	c;
265
266	for (cnt = 0; read(STDIN_FILENO, &c, 1) <= 0; cnt++)
267		if (cnt > 100)
268			die(1);
269	return c;
270}
271