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