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