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. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)subs.c	8.1 (Berkeley) 5/31/93
34  * $FreeBSD: src/games/backgammon/common_source/subs.c,v 1.12 1999/11/30 03:48:27 billf Exp $
35  * $DragonFly: src/games/backgammon/common_source/subs.c,v 1.3 2006/08/08 16:36:11 pavalos Exp $
36  */
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include "back.h"
42 
43 int	buffnum;
44 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 const char  *const descr[] = {
51 	"Usage:  backgammon [-h n r w b pr pw pb tterm sfile]\n",
52 	"\t-h\tgets this list\n\t-n\tdon't ask for rules or instructions",
53 	"\t-r\tplayer is red (implies -n)\n\t-w\tplayer is white (implies -n)",
54 	"\t-b\ttwo players, red and white (implies -n)",
55 	"\t-pr\tprint the board before red's turn",
56 	"\t-pw\tprint the board before white's turn",
57 	"\t-pb\tprint the board before both player's turn",
58 	"\t-tterm\tterminal is a term",
59 	"\t-sfile\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();
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 char
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();
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(char 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 = curr;
192 	c = curc;
193 
194 	if (tflag)  {
195 		curmove (16,0);
196 	}
197 
198 	if (gvalue > 1)  {
199 		writel ("Game value:  ");
200 		wrint (gvalue);
201 		writel (".  ");
202 		if (dlast == -1)
203 			writel (color[0]);
204 		else
205 			writel (color[1]);
206 		writel (" doubled last.");
207 	} else  {
208 		switch (pnum)  {
209 		case -1:			    /* player is red */
210 			writel (plred);
211 			break;
212 		case 0:				    /* player is both colors */
213 			writel (nocomp);
214 			break;
215 		case 1:				    /* player is white */
216 			writel (plwhite);
217 		}
218 	}
219 
220 	if (rscore || wscore)  {
221 		writel ("  ");
222 		wrscore();
223 	}
224 
225 	if (tflag)  {
226 		cline();
227 		curmove (r,c);
228 	}
229 }
230 
231 int
232 quit(void)
233 {
234 	if (tflag)  {
235 		curmove (20,0);
236 		clend();
237 	} else
238 		writec ('\n');
239 	writel ("Are you sure you want to quit?");
240 	if (yorn (0))  {
241 		if (rfl)  {
242 			writel ("Would you like to save this game?");
243 			if (yorn(0))
244 				save(0);
245 		}
246 		cturn = 0;
247 		return (1);
248 	}
249 	return (0);
250 }
251 
252 int
253 yorn(char special)
254 {
255 	char	c;
256 	int	i;
257 
258 	i = 1;
259 	while ( (c = readc()) != 'Y' && c != 'N')  {
260 		if (special && c == special)
261 			return (2);
262 		if (i)  {
263 			if (special)  {
264 				writel ("  (Y, N, or ");
265 				writec (special);
266 				writec (')');
267 			} else
268 				writel ("  (Y or N)");
269 			i = 0;
270 		} else
271 			writec ('\007');
272 	}
273 	if (c == 'Y')
274 		writel ("  Yes.\n");
275 	else
276 		writel ("  No.\n");
277 	if (tflag)
278 		buflush();
279 	return (c == 'Y');
280 }
281 
282 void
283 wrhit(int i)
284 {
285 	writel ("Blot hit on ");
286 	wrint (i);
287 	writec ('.');
288 	writec ('\n');
289 }
290 
291 void
292 nexturn(void)
293 {
294 	int	c;
295 
296 	cturn = -cturn;
297 	c = cturn/abs(cturn);
298 	home = bar;
299 	bar = 25-bar;
300 	offptr += c;
301 	offopp -= c;
302 	inptr += c;
303 	inopp -= c;
304 	Colorptr += c;
305 	colorptr += c;
306 }
307 
308 void
309 getarg(int argc, char **argv)
310 {
311 	char	ch;
312 	int i;
313 
314 	/* process arguments here.  dashes are ignored, nbrw are ignored
315 	   if the game is being recovered */
316 
317 	while ((ch = getopt (argc, argv, "nbrwp:t:s:h")) != -1) {
318 		switch (ch)  {
319 
320 		/* don't ask if rules or instructions needed */
321 		case 'n':
322 			if (rflag)
323 				break;
324 			aflag = 0;
325 			args[acnt++] = strdup ("-n");
326 			break;
327 
328 		/* player is both red and white */
329 		case 'b':
330 			if (rflag)
331 				break;
332 			pnum = 0;
333 			aflag = 0;
334 			args[acnt++] = strdup ("-b");
335 			break;
336 
337 		/* player is red */
338 		case 'r':
339 			if (rflag)
340 				break;
341 			pnum = -1;
342 			aflag = 0;
343 			args[acnt++] = strdup ("-r");
344 			break;
345 
346 		/* player is white */
347 		case 'w':
348 			if (rflag)
349 				break;
350 			pnum = 1;
351 			aflag = 0;
352 			args[acnt++] = strdup ("-w");
353 			break;
354 
355 		/* print board after move according to following character */
356 		case 'p':
357 			if (optarg[0] != 'r' && optarg[0] != 'w' && optarg[0] != 'b')
358 				break;
359 			args[acnt] = strdup ("-p ");
360 			args[acnt++][2] = optarg[0];
361 			if (optarg[0] == 'r')
362 				bflag = 1;
363 			if (optarg[0] == 'w')
364 				bflag = -1;
365 			if (optarg[0] == 'b')
366 				bflag = 0;
367 			break;
368 
369 		case 't':
370 		        tflag = getcaps (optarg);
371 			break;
372 
373 		case 's':
374 			/* recover file */
375 			recover (optarg);
376 			break;
377 		case 'h':
378 			for (i = 0; descr[i] != 0; i++)
379 				puts (descr[i]);
380 			getout();
381 		}
382 	}
383 	argc -= optind;
384 	argv += optind;
385 	if ( argc && argv[0][0] != '\0' )
386 		recover(argv[0]);
387 }
388 
389 void
390 init(void)
391 {
392 	int	i;
393 	for (i = 0; i < 26;)
394 		board[i++] = 0;
395 	board[1] = 2;
396 	board[6] = board[13] = -5;
397 	board[8] = -3;
398 	board[12] = board[19] = 5;
399 	board[17] = 3;
400 	board[24] = -2;
401 	off[0] = off[1] = -15;
402 	in[0] = in[1] = 5;
403 	gvalue = 1;
404 	dlast = 0;
405 }
406 
407 void
408 wrscore(void)
409 {
410 	writel ("Score:  ");
411 	writel (color[1]);
412 	writec (' ');
413 	wrint (rscore);
414 	writel (", ");
415 	writel (color[0]);
416 	writec (' ');
417 	wrint (wscore);
418 }
419 
420 void
421 fixtty(int mode)
422 {
423 	if (tflag)
424 		newpos();
425 	buflush();
426 	tty.c_lflag = mode;
427 	if (tcsetattr (0,TCSANOW,&tty) < 0)
428 		errexit("fixtty");
429 }
430 
431 void
432 getout(void)
433 {
434 	/* go to bottom of screen */
435 	if (tflag)  {
436 		curmove (23,0);
437 		cline();
438 	} else
439 		writec ('\n');
440 
441 	/* fix terminal status */
442 	fixtty (old);
443 	exit(0);
444 }
445 
446 void
447 roll(void)
448 {
449 	char	c;
450 	int	row;
451 	int	col;
452 
453 	if (iroll)  {
454 		row = curr;
455 		col = curc;
456 		if (tflag)  {
457 			curmove (17,0);
458 		} else
459 			writec ('\n');
460 		writel ("ROLL: ");
461 		c = readc();
462 		if (c != '\n')  {
463 			while (c < '1' || c > '6')
464 				c = readc();
465 			D0 = c-'0';
466 			writec (' ');
467 			writec (c);
468 			c = readc();
469 			while (c < '1' || c > '6')
470 				c = readc();
471 			D1 = c-'0';
472 			writec (' ');
473 			writec (c);
474 			if (tflag)  {
475 				curmove (17,0);
476 				cline();
477 				curmove (row,col);
478 			} else
479 				writec ('\n');
480 			return;
481 		}
482 		if (tflag)  {
483 			curmove (17,0);
484 			cline();
485 			curmove (row,col);
486 		} else
487 			writec ('\n');
488 	}
489 	D0 = rnum(6)+1;
490 	D1 = rnum(6)+1;
491 	d0 = 0;
492 }
493