1/*	$NetBSD: subs.c,v 1.16 2007/12/15 19:44:39 perry 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
35static char sccsid[] = "@(#)subs.c	8.1 (Berkeley) 5/31/93";
36#else
37__RCSID("$NetBSD: subs.c,v 1.16 2007/12/15 19:44:39 perry Exp $");
38#endif
39#endif /* not lint */
40
41#include "back.h"
42
43int     buffnum;
44static char outbuff[BUFSIZ];
45
46static const char plred[] = "Player is red, computer is white.";
47static const char plwhite[] = "Player is white, computer is red.";
48static const char nocomp[] = "(No computer play.)";
49
50static 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
63void
64errexit(const char *s)
65{
66	write(2, "\n", 1);
67	perror(s);
68	getout(0);
69}
70
71int
72addbuf(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
84void
85buflush(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
95int
96readc(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
122void
123writec(int c)
124{
125	if (tflag)
126		fancyc(c);
127	else
128		addbuf(c);
129}
130
131void
132writel(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
155void
156proll(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
171void
172wrint(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
186void
187gwrite(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
229int
230quit(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
251int
252yorn(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
281void
282wrhit(int i)
283{
284	writel("Blot hit on ");
285	wrint(i);
286	writec('.');
287	writec('\n');
288}
289
290void
291nexturn(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
307void
308getarg(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
393void
394init(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
412void
413wrscore(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
425void
426fixtty(struct termios *t)
427{
428	if (tflag)
429		newpos();
430	buflush();
431	if (tcsetattr(0, TCSADRAIN, t) < 0)
432		errexit("fixtty");
433}
434
435void
436getout(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
450void
451roll(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