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 <string.h>
40 #include "back.h"
41 
42 int	buffnum;
43 char	outbuff[BUFSIZ];
44 
45 static const char	plred[] = "Player is red, computer is white.";
46 static const char	plwhite[] = "Player is white, computer is red.";
47 static const char	nocomp[] = "(No computer play.)";
48 
49 const char  *const descr[] = {
50 	"Usage:  backgammon [-h n r w b pr pw pb tterm sfile]\n",
51 	"\t-h\tgets this list\n\t-n\tdon't ask for rules or instructions",
52 	"\t-r\tplayer is red (implies -n)\n\t-w\tplayer is white (implies -n)",
53 	"\t-b\ttwo players, red and white (implies -n)",
54 	"\t-pr\tprint the board before red's turn",
55 	"\t-pw\tprint the board before white's turn",
56 	"\t-pb\tprint the board before both player's turn",
57 	"\t-tterm\tterminal is a term",
58 	"\t-sfile\trecover saved game from file",
59 	0
60 };
61 
62 void
63 errexit(const char *s)
64 {
65 	write (2,"\n",1);
66 	perror (s);
67 	getout();
68 }
69 
70 int
71 addbuf(int c)
72 {
73 	buffnum++;
74 	if (buffnum == BUFSIZ)  {
75 		if (write(1,outbuff,BUFSIZ) != BUFSIZ)
76 			errexit ("addbuf (write):");
77 		buffnum = 0;
78 	}
79 	outbuff[buffnum] = c;
80 	return (0);
81 }
82 
83 void
84 buflush(void)
85 {
86 	if (buffnum < 0)
87 		return;
88 	buffnum++;
89 	if (write (1,outbuff,buffnum) != buffnum)
90 		errexit ("buflush (write):");
91 	buffnum = -1;
92 }
93 
94 char
95 readc(void)
96 {
97 	char	c;
98 
99 	if (tflag)  {
100 		cline();
101 		newpos();
102 	}
103 	buflush();
104 	if (read(0,&c,1) != 1)
105 		errexit ("readc");
106 #ifdef WHY_IS_THIS_HARDWIRED_IN_HERE
107 	if (c == '\177')
108 		getout();
109 #endif
110 	if (c == '\033' || c == '\015')
111 		return ('\n');
112 	if (cflag)
113 		return (c);
114 	if (c == '\014')
115 		return ('R');
116 	if (c >= 'a' && c <= 'z')
117 		return (c & 0137);
118 	return (c);
119 }
120 
121 void
122 writec(char c)
123 {
124 	if (tflag)
125 		fancyc (c);
126 	else
127 		addbuf (c);
128 }
129 
130 void
131 writel(const char *l)
132 {
133 #ifdef DEBUG
134 	const char	*s;
135 
136 	if (trace == NULL)
137 		trace = fopen ("bgtrace","w");
138 
139 	fprintf (trace,"writel: \"");
140 	for (s = l; *s; s++) {
141 		if (*s < ' ' || *s == '\177')
142 			fprintf (trace,"^%c",(*s)^0100);
143 		else
144 			putc (*s,trace);
145 	}
146 	fprintf (trace,"\"\n");
147 	fflush (trace);
148 #endif
149 
150 	while (*l)
151 		writec (*l++);
152 }
153 
154 void
155 proll(void)
156 {
157 	if (d0)
158 		swap;
159 	if (cturn == 1)
160 		writel ("Red's roll:  ");
161 	else
162 		writel ("White's roll:  ");
163 	writec (D0+'0');
164 	writec ('\040');
165 	writec (D1+'0');
166 	if (tflag)
167 		cline();
168 }
169 
170 void
171 wrint(int n)
172 {
173 	int	i, j, t;
174 
175 	for (i = 4; i > 0; i--)  {
176 		t = 1;
177 		for (j = 0; j<i; j++)
178 			t *= 10;
179 		if (n > t-1)
180 			writec ((n/t)%10+'0');
181 	}
182 	writec (n%10+'0');
183 }
184 
185 void
186 gwrite(void)
187 {
188 	int	r, c;
189 
190 	r = curr;
191 	c = curc;
192 
193 	if (tflag)  {
194 		curmove (16,0);
195 	}
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 
224 	if (tflag)  {
225 		cline();
226 		curmove (r,c);
227 	}
228 }
229 
230 int
231 quit(void)
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(char 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(int argc, char **argv)
309 {
310 	char	ch;
311 	int i;
312 
313 	/* process arguments here.  dashes are ignored, nbrw are ignored
314 	   if the game is being recovered */
315 
316 	while ((ch = getopt (argc, argv, "nbrwp:t:s:h")) != -1) {
317 		switch (ch)  {
318 
319 		/* don't ask if rules or instructions needed */
320 		case 'n':
321 			if (rflag)
322 				break;
323 			aflag = 0;
324 			args[acnt++] = strdup ("-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++] = strdup ("-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++] = strdup ("-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++] = strdup ("-w");
352 			break;
353 
354 		/* print board after move according to following character */
355 		case 'p':
356 			if (optarg[0] != 'r' && optarg[0] != 'w' && optarg[0] != 'b')
357 				break;
358 			args[acnt] = strdup ("-p ");
359 			args[acnt++][2] = optarg[0];
360 			if (optarg[0] == 'r')
361 				bflag = 1;
362 			if (optarg[0] == 'w')
363 				bflag = -1;
364 			if (optarg[0] == 'b')
365 				bflag = 0;
366 			break;
367 
368 		case 't':
369 		        tflag = getcaps (optarg);
370 			break;
371 
372 		case 's':
373 			/* recover file */
374 			recover (optarg);
375 			break;
376 		case 'h':
377 			for (i = 0; descr[i] != 0; i++)
378 				puts (descr[i]);
379 			getout();
380 		}
381 	}
382 	argc -= optind;
383 	argv += optind;
384 	if ( argc && argv[0][0] != '\0' )
385 		recover(argv[0]);
386 }
387 
388 void
389 init(void)
390 {
391 	int	i;
392 	for (i = 0; i < 26;)
393 		board[i++] = 0;
394 	board[1] = 2;
395 	board[6] = board[13] = -5;
396 	board[8] = -3;
397 	board[12] = board[19] = 5;
398 	board[17] = 3;
399 	board[24] = -2;
400 	off[0] = off[1] = -15;
401 	in[0] = in[1] = 5;
402 	gvalue = 1;
403 	dlast = 0;
404 }
405 
406 void
407 wrscore(void)
408 {
409 	writel ("Score:  ");
410 	writel (color[1]);
411 	writec (' ');
412 	wrint (rscore);
413 	writel (", ");
414 	writel (color[0]);
415 	writec (' ');
416 	wrint (wscore);
417 }
418 
419 void
420 fixtty(int mode)
421 {
422 	if (tflag)
423 		newpos();
424 	buflush();
425 	tty.sg_flags = mode;
426 	if (ioctl(0, TIOCSETP, &tty) < 0)
427 		errexit("fixtty");
428 }
429 
430 void
431 getout(void)
432 {
433 	/* go to bottom of screen */
434 	if (tflag)  {
435 		curmove (23,0);
436 		cline();
437 	} else
438 		writec ('\n');
439 
440 	/* fix terminal status */
441 	fixtty (old);
442 	exit(0);
443 }
444 
445 void
446 roll(void)
447 {
448 	char	c;
449 	int	row;
450 	int	col;
451 
452 	if (iroll)  {
453 		row = curr;
454 		col = curc;
455 		if (tflag)  {
456 			curmove (17,0);
457 		} else
458 			writec ('\n');
459 		writel ("ROLL: ");
460 		c = readc();
461 		if (c != '\n')  {
462 			while (c < '1' || c > '6')
463 				c = readc();
464 			D0 = c-'0';
465 			writec (' ');
466 			writec (c);
467 			c = readc();
468 			while (c < '1' || c > '6')
469 				c = readc();
470 			D1 = c-'0';
471 			writec (' ');
472 			writec (c);
473 			if (tflag)  {
474 				curmove (17,0);
475 				cline();
476 				curmove (row,col);
477 			} else
478 				writec ('\n');
479 			return;
480 		}
481 		if (tflag)  {
482 			curmove (17,0);
483 			cline();
484 			curmove (row,col);
485 		} else
486 			writec ('\n');
487 	}
488 	D0 = rnum(6)+1;
489 	D1 = rnum(6)+1;
490 	d0 = 0;
491 }
492