xref: /netbsd-src/games/backgammon/common_source/subs.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: subs.c,v 1.17 2009/08/12 05:17:57 dholland Exp $	*/
2 
3 /*
4  * Copyright (c) 1980, 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
35 static char sccsid[] = "@(#)subs.c	8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: subs.c,v 1.17 2009/08/12 05:17:57 dholland Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #include "back.h"
42 
43 int     buffnum;
44 static char outbuff[BUFSIZ];
45 
46 static const char plred[] = "Player is red, computer is white.";
47 static const char plwhite[] = "Player is white, computer is red.";
48 static const char nocomp[] = "(No computer play.)";
49 
50 static const char *const descr[] = {
51 	"Usage:  backgammon [-] [n r w b pr pw pb t3a]\n",
52 	"\t-\tgets this list\n\tn\tdon't ask for rules or instructions",
53 	"\tr\tplayer is red (implies n)\n\tw\tplayer is white (implies n)",
54 	"\tb\ttwo players, red and white (implies n)",
55 	"\tpr\tprint the board before red's turn",
56 	"\tpw\tprint the board before white's turn",
57 	"\tpb\tprint the board before both player's turn",
58 	"\tterm\tterminal is a term",
59 	"\tsfile\trecover saved game from file",
60 	0
61 };
62 
63 void
64 errexit(const char *s)
65 {
66 	write(2, "\n", 1);
67 	perror(s);
68 	getout(0);
69 }
70 
71 int
72 addbuf(int c)
73 {
74 	buffnum++;
75 	if (buffnum == BUFSIZ) {
76 		if (write(1, outbuff, BUFSIZ) != BUFSIZ)
77 			errexit("addbuf (write):");
78 		buffnum = 0;
79 	}
80 	outbuff[buffnum] = c;
81 	return (0);
82 }
83 
84 void
85 buflush(void)
86 {
87 	if (buffnum < 0)
88 		return;
89 	buffnum++;
90 	if (write(1, outbuff, buffnum) != buffnum)
91 		errexit("buflush (write):");
92 	buffnum = -1;
93 }
94 
95 int
96 readc(void)
97 {
98 	char    c;
99 
100 	if (tflag) {
101 		cline();
102 		newpos();
103 	}
104 	buflush();
105 	if (read(0, &c, 1) != 1)
106 		errexit("readc");
107 #ifdef WHY_IS_THIS_HARDWIRED_IN_HERE
108 	if (c == '\177')
109 		getout(0);
110 #endif
111 	if (c == '\033' || c == '\015')
112 		return ('\n');
113 	if (cflag)
114 		return (c);
115 	if (c == '\014')
116 		return ('R');
117 	if (c >= 'a' && c <= 'z')
118 		return (c & 0137);
119 	return (c);
120 }
121 
122 void
123 writec(int c)
124 {
125 	if (tflag)
126 		fancyc(c);
127 	else
128 		addbuf(c);
129 }
130 
131 void
132 writel(const char *l)
133 {
134 #ifdef DEBUG
135 	const char   *s;
136 
137 	if (trace == NULL)
138 		trace = fopen("bgtrace", "w");
139 
140 	fprintf(trace, "writel: \"");
141 	for (s = l; *s; s++) {
142 		if (*s < ' ' || *s == '\177')
143 			fprintf(trace, "^%c", (*s) ^ 0100);
144 		else
145 			putc(*s, trace);
146 	}
147 	fprintf(trace, "\"\n");
148 	fflush(trace);
149 #endif
150 
151 	while (*l)
152 		writec(*l++);
153 }
154 
155 void
156 proll(void)
157 {
158 	if (d0)
159 		swap;
160 	if (cturn == 1)
161 		writel("Red's roll:  ");
162 	else
163 		writel("White's roll:  ");
164 	writec(D0 + '0');
165 	writec('\040');
166 	writec(D1 + '0');
167 	if (tflag)
168 		cline();
169 }
170 
171 void
172 wrint(int n)
173 {
174 	int     i, j, t;
175 
176 	for (i = 4; i > 0; i--) {
177 		t = 1;
178 		for (j = 0; j < i; j++)
179 			t *= 10;
180 		if (n > t - 1)
181 			writec((n / t) % 10 + '0');
182 	}
183 	writec(n % 10 + '0');
184 }
185 
186 void
187 gwrite(void)
188 {
189 	int     r, c;
190 
191 	r = c = 0;
192 	if (tflag) {
193 		r = curr;
194 		c = curc;
195 		curmove(16, 0);
196 	}
197 	if (gvalue > 1) {
198 		writel("Game value:  ");
199 		wrint(gvalue);
200 		writel(".  ");
201 		if (dlast == -1)
202 			writel(color[0]);
203 		else
204 			writel(color[1]);
205 		writel(" doubled last.");
206 	} else {
207 		switch (pnum) {
208 		case -1:	/* player is red */
209 			writel(plred);
210 			break;
211 		case 0:	/* player is both colors */
212 			writel(nocomp);
213 			break;
214 		case 1:	/* player is white */
215 			writel(plwhite);
216 		}
217 	}
218 
219 	if (rscore || wscore) {
220 		writel("  ");
221 		wrscore();
222 	}
223 	if (tflag) {
224 		cline();
225 		curmove(r, c);
226 	}
227 }
228 
229 int
230 quit(void)
231 {
232 
233 	if (tflag) {
234 		curmove(20, 0);
235 		clend();
236 	} else
237 		writec('\n');
238 	writel("Are you sure you want to quit?");
239 	if (yorn(0)) {
240 		if (rfl) {
241 			writel("Would you like to save this game?");
242 			if (yorn(0))
243 				save(0);
244 		}
245 		cturn = 0;
246 		return (1);
247 	}
248 	return (0);
249 }
250 
251 int
252 yorn(int special)
253 {
254 	char    c;
255 	int     i;
256 
257 	i = 1;
258 	while ((c = readc()) != 'Y' && c != 'N') {
259 		if (special && c == special)
260 			return (2);
261 		if (i) {
262 			if (special) {
263 				writel("  (Y, N, or ");
264 				writec(special);
265 				writec(')');
266 			} else
267 				writel("  (Y or N)");
268 			i = 0;
269 		} else
270 			writec('\007');
271 	}
272 	if (c == 'Y')
273 		writel("  Yes.\n");
274 	else
275 		writel("  No.\n");
276 	if (tflag)
277 		buflush();
278 	return (c == 'Y');
279 }
280 
281 void
282 wrhit(int i)
283 {
284 	writel("Blot hit on ");
285 	wrint(i);
286 	writec('.');
287 	writec('\n');
288 }
289 
290 void
291 nexturn(void)
292 {
293 	int     c;
294 
295 	cturn = -cturn;
296 	c = cturn / abs(cturn);
297 	home = bar;
298 	bar = 25 - bar;
299 	offptr += c;
300 	offopp -= c;
301 	inptr += c;
302 	inopp -= c;
303 	Colorptr += c;
304 	colorptr += c;
305 }
306 
307 void
308 getarg(char ***arg)
309 {
310 	char  **s;
311 
312 	/* process arguments here.  dashes are ignored, nbrw are ignored if
313 	 * the game is being recovered */
314 
315 	s = *arg;
316 	while (*s && s[0][0] == '-') {
317 		switch (s[0][1]) {
318 
319 			/* don't ask if rules or instructions needed */
320 		case 'n':
321 			if (rflag)
322 				break;
323 			aflag = 0;
324 			args[acnt++] = 'n';
325 			break;
326 
327 			/* player is both red and white */
328 		case 'b':
329 			if (rflag)
330 				break;
331 			pnum = 0;
332 			aflag = 0;
333 			args[acnt++] = 'b';
334 			break;
335 
336 			/* player is red */
337 		case 'r':
338 			if (rflag)
339 				break;
340 			pnum = -1;
341 			aflag = 0;
342 			args[acnt++] = 'r';
343 			break;
344 
345 			/* player is white */
346 		case 'w':
347 			if (rflag)
348 				break;
349 			pnum = 1;
350 			aflag = 0;
351 			args[acnt++] = 'w';
352 			break;
353 
354 			/* print board after move according to following
355 			 * character */
356 		case 'p':
357 			if (s[0][2] != 'r' && s[0][2] != 'w' && s[0][2] != 'b')
358 				break;
359 			args[acnt++] = 'p';
360 			args[acnt++] = s[0][2];
361 			if (s[0][2] == 'r')
362 				bflag = 1;
363 			if (s[0][2] == 'w')
364 				bflag = -1;
365 			if (s[0][2] == 'b')
366 				bflag = 0;
367 			break;
368 
369 		case 't':
370 			if (s[0][2] == '\0') {	/* get terminal caps */
371 				s++;
372 				tflag = getcaps(*s);
373 			} else
374 				tflag = getcaps(&s[0][2]);
375 			break;
376 
377 		case 's':
378 			s++;
379 			/* recover file */
380 			if (s[0] == NULL) {
381 				writel("No save file named\n");
382 				getout(0);
383 			} else
384 				recover(s[0]);
385 			break;
386 		}
387 		s++;
388 	}
389 	if (s[0] != 0)
390 		recover(s[0]);
391 }
392 
393 void
394 init(void)
395 {
396 	int     i;
397 
398 	for (i = 0; i < 26;)
399 		board[i++] = 0;
400 	board[1] = 2;
401 	board[6] = board[13] = -5;
402 	board[8] = -3;
403 	board[12] = board[19] = 5;
404 	board[17] = 3;
405 	board[24] = -2;
406 	off[0] = off[1] = -15;
407 	in[0] = in[1] = 5;
408 	gvalue = 1;
409 	dlast = 0;
410 }
411 
412 void
413 wrscore(void)
414 {
415 	writel("Score:  ");
416 	writel(color[1]);
417 	writec(' ');
418 	wrint(rscore);
419 	writel(", ");
420 	writel(color[0]);
421 	writec(' ');
422 	wrint(wscore);
423 }
424 
425 void
426 fixtty(struct termios *t)
427 {
428 	if (tflag)
429 		newpos();
430 	buflush();
431 	if (tcsetattr(0, TCSADRAIN, t) < 0)
432 		errexit("fixtty");
433 }
434 
435 void
436 getout(int dummy __unused)
437 {
438 	/* go to bottom of screen */
439 	if (tflag) {
440 		curmove(23, 0);
441 		cline();
442 	} else
443 		writec('\n');
444 
445 	/* fix terminal status */
446 	fixtty(&old);
447 	exit(0);
448 }
449 
450 void
451 roll(void)
452 {
453 	char    c;
454 	int     row;
455 	int     col;
456 
457 	row = col = 0;
458 	if (iroll) {
459 		if (tflag) {
460 			row = curr;
461 			col = curc;
462 			curmove(17, 0);
463 		} else
464 			writec('\n');
465 		writel("ROLL: ");
466 		c = readc();
467 		if (c != '\n') {
468 			while (c < '1' || c > '6')
469 				c = readc();
470 			D0 = c - '0';
471 			writec(' ');
472 			writec(c);
473 			c = readc();
474 			while (c < '1' || c > '6')
475 				c = readc();
476 			D1 = c - '0';
477 			writec(' ');
478 			writec(c);
479 			if (tflag) {
480 				curmove(17, 0);
481 				cline();
482 				curmove(row, col);
483 			} else
484 				writec('\n');
485 			return;
486 		}
487 		if (tflag) {
488 			curmove(17, 0);
489 			cline();
490 			curmove(row, col);
491 		} else
492 			writec('\n');
493 	}
494 	D0 = rnum(6) + 1;
495 	D1 = rnum(6) + 1;
496 	d0 = 0;
497 }
498