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