1 /*-
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)subs.c	8.1 (Berkeley) 5/31/93
30  * $FreeBSD: src/games/backgammon/common_source/subs.c,v 1.12 1999/11/30 03:48:27 billf Exp $
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "back.h"
37 
38 int	buffnum;
39 char	outbuff[BUFSIZ];
40 
41 static const char	plred[] = "Player is red, computer is white.";
42 static const char	plwhite[] = "Player is white, computer is red.";
43 static const char	nocomp[] = "(No computer play.)";
44 
45 const char  *const descr[] = {
46 	"Usage:  backgammon [-h n r w b pr pw pb tterm sfile]\n",
47 	"\t-h\tgets this list\n\t-n\tdon't ask for rules or instructions",
48 	"\t-r\tplayer is red (implies -n)\n\t-w\tplayer is white (implies -n)",
49 	"\t-b\ttwo players, red and white (implies -n)",
50 	"\t-pr\tprint the board before red's turn",
51 	"\t-pw\tprint the board before white's turn",
52 	"\t-pb\tprint the board before both player's turn",
53 	"\t-tterm\tterminal is a term",
54 	"\t-sfile\trecover saved game from file",
55 	0
56 };
57 
58 void
59 errexit(const char *s)
60 {
61 	write(2, "\n", 1);
62 	perror(s);
63 	getout(0);
64 }
65 
66 int
67 addbuf(int c)
68 {
69 	buffnum++;
70 	if (buffnum == BUFSIZ) {
71 		if (write(1, outbuff, BUFSIZ) != BUFSIZ)
72 			errexit("addbuf (write):");
73 		buffnum = 0;
74 	}
75 	outbuff[buffnum] = c;
76 	return (0);
77 }
78 
79 void
80 buflush(void)
81 {
82 	if (buffnum < 0)
83 		return;
84 	buffnum++;
85 	if (write(1, outbuff, buffnum) != buffnum)
86 		errexit("buflush (write):");
87 	buffnum = -1;
88 }
89 
90 char
91 readc(void)
92 {
93 	char c;
94 
95 	if (tflag) {
96 		cline();
97 		newpos();
98 	}
99 	buflush();
100 	if (read(0, &c, 1) != 1)
101 		errexit("readc");
102 #ifdef WHY_IS_THIS_HARDWIRED_IN_HERE
103 	if (c == '\177')
104 		getout(0);
105 #endif
106 	if (c == '\033' || c == '\015')
107 		return ('\n');
108 	if (cflag)
109 		return (c);
110 	if (c == '\014')
111 		return ('R');
112 	if (c >= 'a' && c <= 'z')
113 		return (c & 0137);
114 	return (c);
115 }
116 
117 void
118 writec(char c)
119 {
120 	if (tflag)
121 		fancyc(c);
122 	else
123 		addbuf(c);
124 }
125 
126 void
127 writel(const char *l)
128 {
129 #ifdef DEBUG
130 	const char *s;
131 
132 	if (trace == NULL)
133 		trace = fopen("bgtrace", "w");
134 
135 	fprintf(trace, "writel: \"");
136 	for (s = l; *s; s++) {
137 		if (*s < ' ' || *s == '\177')
138 			fprintf(trace, "^%c", (*s) ^ 0100);
139 		else
140 			putc(*s, trace);
141 	}
142 	fprintf(trace, "\"\n");
143 	fflush(trace);
144 #endif
145 
146 	while (*l)
147 		writec(*l++);
148 }
149 
150 void
151 proll(void)
152 {
153 	if (d0)
154 		swap;
155 	if (cturn == 1)
156 		writel("Red's roll:  ");
157 	else
158 		writel("White's roll:  ");
159 	writec(D0 + '0');
160 	writec('\040');
161 	writec(D1 + '0');
162 	if (tflag)
163 		cline();
164 }
165 
166 void
167 wrint(int n)
168 {
169 	int i, j, t;
170 
171 	for (i = 4; i > 0; i--) {
172 		t = 1;
173 		for (j = 0; j < i; j++)
174 			t *= 10;
175 		if (n > t - 1)
176 			writec((n / t) % 10 + '0');
177 	}
178 	writec(n % 10 + '0');
179 }
180 
181 void
182 gwrite(void)
183 {
184 	int r, c;
185 
186 	r = curr;
187 	c = curc;
188 
189 	if (tflag)
190 		curmove(16, 0);
191 
192 	if (gvalue > 1) {
193 		writel("Game value:  ");
194 		wrint(gvalue);
195 		writel(".  ");
196 		if (dlast == -1)
197 			writel(color[0]);
198 		else
199 			writel(color[1]);
200 		writel(" doubled last.");
201 	} else {
202 		switch (pnum) {
203 		case -1:		/* player is red */
204 			writel(plred);
205 			break;
206 		case 0:			/* player is both colors */
207 			writel(nocomp);
208 			break;
209 		case 1:			/* player is white */
210 			writel(plwhite);
211 		}
212 	}
213 
214 	if (rscore || wscore) {
215 		writel("  ");
216 		wrscore();
217 	}
218 	if (tflag) {
219 		cline();
220 		curmove(r, c);
221 	}
222 }
223 
224 int
225 quit(void)
226 {
227 	if (tflag) {
228 		curmove(20, 0);
229 		clend();
230 	} else
231 		writec('\n');
232 	writel("Are you sure you want to quit?");
233 	if (yorn(0)) {
234 		if (rfl) {
235 			writel("Would you like to save this game?");
236 			if (yorn(0))
237 				save(0);
238 		}
239 		cturn = 0;
240 		return (1);
241 	}
242 	return (0);
243 }
244 
245 int
246 yorn(char special)
247 {
248 	char c;
249 	int i;
250 
251 	i = 1;
252 	while ((c = readc()) != 'Y' && c != 'N') {
253 		if (special && c == special)
254 			return (2);
255 		if (i) {
256 			if (special) {
257 				writel("  (Y, N, or ");
258 				writec(special);
259 				writec(')');
260 			} else
261 				writel("  (Y or N)");
262 			i = 0;
263 		} else
264 			writec('\007');
265 	}
266 	if (c == 'Y')
267 		writel("  Yes.\n");
268 	else
269 		writel("  No.\n");
270 	if (tflag)
271 		buflush();
272 	return (c == 'Y');
273 }
274 
275 void
276 wrhit(int i)
277 {
278 	writel("Blot hit on ");
279 	wrint(i);
280 	writec('.');
281 	writec('\n');
282 }
283 
284 void
285 nexturn(void)
286 {
287 	int c;
288 
289 	cturn = -cturn;
290 	c = cturn / abs(cturn);
291 	home = bar;
292 	bar = 25 - bar;
293 	offptr += c;
294 	offopp -= c;
295 	inptr += c;
296 	inopp -= c;
297 	Colorptr += c;
298 	colorptr += c;
299 }
300 
301 void
302 getarg(int argc, char **argv)
303 {
304 	char ch;
305 	int i;
306 
307 	/* process arguments here.  dashes are ignored, nbrw are ignored if
308 	 * the game is being recovered */
309 
310 	while ((ch = getopt(argc, argv, "nbrwp:t:s:h")) != -1) {
311 		switch (ch) {
312 		/* don't ask if rules or instructions needed */
313 		case 'n':
314 			if (rflag)
315 				break;
316 			aflag = 0;
317 			args[acnt++] = strdup("-n");
318 			break;
319 
320 		/* player is both red and white */
321 		case 'b':
322 			if (rflag)
323 				break;
324 			pnum = 0;
325 			aflag = 0;
326 			args[acnt++] = strdup("-b");
327 			break;
328 
329 		/* player is red */
330 		case 'r':
331 			if (rflag)
332 				break;
333 			pnum = -1;
334 			aflag = 0;
335 			args[acnt++] = strdup("-r");
336 			break;
337 
338 		/* player is white */
339 		case 'w':
340 			if (rflag)
341 				break;
342 			pnum = 1;
343 			aflag = 0;
344 			args[acnt++] = strdup("-w");
345 			break;
346 
347 		/* print board after move according to following character */
348 		case 'p':
349 			if (optarg[0] != 'r' && optarg[0] != 'w' &&
350 			    optarg[0] != 'b')
351 				break;
352 			args[acnt] = strdup("-p ");
353 			args[acnt++][2] = optarg[0];
354 			if (optarg[0] == 'r')
355 				bflag = 1;
356 			if (optarg[0] == 'w')
357 				bflag = -1;
358 			if (optarg[0] == 'b')
359 				bflag = 0;
360 			break;
361 
362 		case 't':
363 			tflag = getcaps(optarg);
364 			break;
365 
366 		case 's':
367 			/* recover file */
368 			recover(optarg);
369 			break;
370 		case 'h':
371 			for (i = 0; descr[i] != NULL; i++)
372 				puts(descr[i]);
373 			getout(0);
374 		}
375 	}
376 	argc -= optind;
377 	argv += optind;
378 	if (argc && argv[0][0] != '\0')
379 		recover(argv[0]);
380 }
381 
382 void
383 init(void)
384 {
385 	int i;
386 
387 	for (i = 0; i < 26; )
388 		board[i++] = 0;
389 	board[1] = 2;
390 	board[6] = board[13] = -5;
391 	board[8] = -3;
392 	board[12] = board[19] = 5;
393 	board[17] = 3;
394 	board[24] = -2;
395 	off[0] = off[1] = -15;
396 	in[0] = in[1] = 5;
397 	gvalue = 1;
398 	dlast = 0;
399 }
400 
401 void
402 wrscore(void)
403 {
404 	writel("Score:  ");
405 	writel(color[1]);
406 	writec(' ');
407 	wrint(rscore);
408 	writel(", ");
409 	writel(color[0]);
410 	writec(' ');
411 	wrint(wscore);
412 }
413 
414 void
415 fixtty(int mode)
416 {
417 	if (tflag)
418 		newpos();
419 	buflush();
420 	tty.c_lflag = mode;
421 	if (tcsetattr(0, TCSANOW, &tty) < 0)
422 		errexit("fixtty");
423 }
424 
425 void
426 getout(__unused int sig)
427 {
428 	/* go to bottom of screen */
429 	if (tflag) {
430 		curmove(23, 0);
431 		cline();
432 	} else
433 		writec('\n');
434 
435 	/* fix terminal status */
436 	fixtty(old);
437 	exit(0);
438 }
439 
440 void
441 roll(void)
442 {
443 	char c;
444 	int row;
445 	int col;
446 
447 	if (iroll) {
448 		row = curr;
449 		col = curc;
450 		if (tflag)
451 			curmove(17, 0);
452 		else
453 			writec('\n');
454 		writel("ROLL: ");
455 		c = readc();
456 		if (c != '\n') {
457 			while (c < '1' || c > '6')
458 				c = readc();
459 			D0 = c - '0';
460 			writec(' ');
461 			writec(c);
462 			c = readc();
463 			while (c < '1' || c > '6')
464 				c = readc();
465 			D1 = c - '0';
466 			writec(' ');
467 			writec(c);
468 			if (tflag) {
469 				curmove(17, 0);
470 				cline();
471 				curmove(row, col);
472 			} else
473 				writec('\n');
474 			return;
475 		}
476 		if (tflag) {
477 			curmove(17, 0);
478 			cline();
479 			curmove(row, col);
480 		} else
481 			writec('\n');
482 	}
483 	D0 = rnum(6) + 1;
484 	D1 = rnum(6) + 1;
485 	d0 = 0;
486 }
487