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