1 /*
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 05/31/93";
16 #endif /* not lint */
17 
18 #include <stdio.h>
19 #include "back.h"
20 
21 #define MVPAUSE	5				/* time to sleep when stuck */
22 #define MAXUSERS 35				/* maximum number of users */
23 
24 char	*instr[];				/* text of instructions */
25 char	*message[];				/* update message */
26 char	ospeed;					/* tty output speed */
27 
28 char	*helpm[] = {				/* help message */
29 	"Enter a space or newline to roll, or",
30 	"     R   to reprint the board\tD   to double",
31 	"     S   to save the game\tQ   to quit",
32 	0
33 };
34 
35 char	*contin[] = {				/* pause message */
36 	"(Type a newline to continue.)",
37 	"",
38 	0
39 };
40 
41 static char user1a[] =
42 	"Sorry, you cannot play backgammon when there are more than ";
43 static char user1b[] =
44 	" users\non the system.";
45 static char user2a[] =
46 	"\nThere are now more than ";
47 static char user2b[] =
48 	" users on the system, so you cannot play\nanother game.  ";
49 static char	rules[] = "\nDo you want the rules of the game?";
50 static char	noteach[] = "Teachgammon not available!\n\007";
51 static char	need[] = "Do you need instructions for this program?";
52 static char	askcol[] =
53 	"Enter 'r' to play red, 'w' to play white, 'b' to play both:";
54 static char	rollr[] = "Red rolls a ";
55 static char	rollw[] = ".  White rolls a ";
56 static char	rstart[] = ".  Red starts.\n";
57 static char	wstart[] = ".  White starts.\n";
58 static char	toobad1[] = "Too bad, ";
59 static char	unable[] = " is unable to use that roll.\n";
60 static char	toobad2[] = ".  Too bad, ";
61 static char	cantmv[] = " can't move.\n";
62 static char	bgammon[] = "Backgammon!  ";
63 static char	gammon[] = "Gammon!  ";
64 static char	again[] = ".\nWould you like to play again?";
65 static char	svpromt[] = "Would you like to save this game?";
66 
67 static char	password[] = "losfurng";
68 static char	pbuf[10];
69 
70 main (argc,argv)
71 int	argc;
72 char	**argv;
73 
74 {
75 	register int	i;		/* non-descript index */
76 	register int	l;		/* non-descript index */
77 	register char	c;		/* non-descript character storage */
78 	long	t;			/* time for random num generator */
79 
80 	/* initialization */
81 	bflag = 2;					/* default no board */
82 	signal (2,getout);				/* trap interrupts */
83 	if (gtty (0,&tty) == -1)			/* get old tty mode */
84 		errexit ("backgammon(gtty)");
85 	old = tty.sg_flags;
86 #ifdef V7
87 	raw = ((noech = old & ~ECHO) | CBREAK);		/* set up modes */
88 #else
89 	raw = ((noech = old & ~ECHO) | RAW);		/* set up modes */
90 #endif
91 	ospeed = tty.sg_ospeed;				/* for termlib */
92 
93 							/* check user count */
94 # ifdef CORY
95 	if (ucount() > MAXUSERS)  {
96 		writel (user1a);
97 		wrint (MAXUSERS);
98 		writel (user1b);
99 		getout();
100 	}
101 # endif
102 
103 							/* get terminal
104 							 * capabilities, and
105 					   		 * decide if it can
106 							 * cursor address */
107 	tflag = getcaps (getenv ("TERM"));
108 							/* use whole screen
109 							 * for text */
110 	if (tflag)
111 		begscr = 0;
112 	t = time(0);
113 	srandom(t);					/* 'random' seed */
114 
115 #ifdef V7
116 	while (*++argv != 0)				/* process arguments */
117 #else
118 	while (*++argv != -1)				/* process arguments */
119 #endif
120 		getarg (&argv);
121 	args[acnt] = '\0';
122 	if (tflag)  {					/* clear screen */
123 		noech &= ~(CRMOD|XTABS);
124 		raw &= ~(CRMOD|XTABS);
125 		clear();
126 	}
127 	fixtty (raw);					/* go into raw mode */
128 
129 							/* check if restored
130 							 * game and save flag
131 							 * for later */
132 	if (rfl = rflag)  {
133 		text (message);				/* print message */
134 		text (contin);
135 		wrboard();				/* print board */
136 							/* if new game, pretend
137 							 * to be a non-restored
138 							 * game */
139 		if (cturn == 0)
140 			rflag = 0;
141 	} else  {
142 		rscore = wscore = 0;			/* zero score */
143 		text (message);				/* update message
144 							 * without pausing */
145 
146 		if (aflag)  {				/* print rules */
147 			writel (rules);
148 			if (yorn(0))  {
149 
150 				fixtty (old);		/* restore tty */
151 				execl (TEACH,"teachgammon",args,0);
152 
153 				tflag = 0;		/* error! */
154 				writel (noteach);
155 				exit();
156 			} else  {			/* if not rules, then
157 							 * instructions */
158 				writel (need);
159 				if (yorn(0))  {		/* print instructions */
160 					clear();
161 					text (instr);
162 				}
163 			}
164 		}
165 
166 		init();					/* initialize board */
167 
168 		if (pnum == 2)  {			/* ask for color(s) */
169 			writec ('\n');
170 			writel (askcol);
171 			while (pnum == 2)  {
172 				c = readc();
173 				switch (c)  {
174 
175 				case 'R':		/* red */
176 					pnum = -1;
177 					break;
178 
179 				case 'W':		/* white */
180 					pnum = 1;
181 					break;
182 
183 				case 'B':		/* both */
184 					pnum = 0;
185 					break;
186 
187 				case 'P':
188 					if (iroll)
189 						break;
190 					if (tflag)
191 						curmove (curr,0);
192 					else
193 						writec ('\n');
194 					writel ("Password:");
195 					signal (14,getout);
196 					cflag = 1;
197 					alarm (10);
198 					for (i = 0; i < 10; i++)  {
199 						pbuf[i] = readc();
200 						if (pbuf[i] == '\n')
201 							break;
202 					}
203 					if (i == 10)
204 						while (readc() != '\n');
205 					alarm (0);
206 					cflag = 0;
207 					if (i < 10)
208 						pbuf[i] = '\0';
209 					for (i = 0; i < 9; i++)
210 						if (pbuf[i] != password[i])
211 							getout();
212 					iroll = 1;
213 					if (tflag)
214 						curmove (curr,0);
215 					else
216 						writec ('\n');
217 					writel (askcol);
218 					break;
219 
220 				default:		/* error */
221 					writec ('\007');
222 				}
223 			}
224 		} else  if (!aflag)
225 							/* pause to read
226 							 * message */
227 			text (contin);
228 
229 		wrboard();				/* print board */
230 
231 		if (tflag)
232 			curmove (18,0);
233 		else
234 			writec ('\n');
235 	}
236 							/* limit text to bottom
237 							 * of screen */
238 	if (tflag)
239 		begscr = 17;
240 
241 	for (;;)  {					/* begin game! */
242 							/* initial roll if
243 							 * needed */
244 		if ((! rflag) || raflag)
245 			roll();
246 
247 							/* perform ritual of
248 							 * first roll */
249 		if (! rflag)  {
250 			if (tflag)
251 				curmove (17,0);
252 			while (D0 == D1)		/* no doubles */
253 				roll();
254 
255 							/* print rolls */
256 			writel (rollr);
257 			writec (D0+'0');
258 			writel (rollw);
259 			writec (D1+'0');
260 
261 							/* winner goes first */
262 			if (D0 > D1)  {
263 				writel (rstart);
264 				cturn = 1;
265 			} else  {
266 				writel (wstart);
267 				cturn = -1;
268 			}
269 		}
270 
271 							/* initalize variables
272 							 * according to whose
273 							 * turn it is */
274 
275 		if (cturn == 1)  {			    /* red */
276 			home = 25;
277 			bar = 0;
278 			inptr = &in[1];
279 			inopp = &in[0];
280 			offptr = &off[1];
281 			offopp = &off[0];
282 			Colorptr = &color[1];
283 			colorptr = &color[3];
284 			colen = 3;
285 		} else  {				    /* white */
286 			home = 0;
287 			bar = 25;
288 			inptr = &in[0];
289 			inopp = &in[1];
290 			offptr = &off[0];
291 			offopp = &off[1];
292 			Colorptr = &color[0];
293 			colorptr = &color[2];
294 			colen = 5;
295 		}
296 
297 							/* do first move
298 							 * (special case) */
299 		if (! (rflag && raflag))  {
300 			if (cturn == pnum)		/* computer's move */
301 				move (0);
302 			else  {				/* player's move */
303 				mvlim = movallow();
304 							/* reprint roll */
305 				if (tflag)
306 					curmove (cturn == -1? 18: 19,0);
307 				proll();
308 				getmove();		/* get player's move */
309 			}
310 		}
311 		if (tflag)  {
312 			curmove (17,0);
313 			cline();
314 			begscr = 18;
315 		}
316 
317 							/* no longer any diff-
318 							 * erence between normal
319 							 * game and recovered
320 							 * game. */
321 		rflag = 0;
322 
323 							/* move as long as it's
324 							 * someone's turn */
325 		while (cturn == 1 || cturn == -1)  {
326 
327 							/* board maintainence */
328 			if (tflag)
329 				refresh();		/* fix board */
330 			else
331 							/* redo board if -p */
332 				if (cturn == bflag || bflag == 0)
333 					wrboard();
334 
335 							/* do computer's move */
336 			if (cturn == pnum)  {
337 				move (1);
338 
339 							/* see if double
340 							 * refused */
341 				if (cturn == -2 || cturn == 2)
342 					break;
343 
344 							/* check for winning
345 							 * move */
346 				if (*offopp == 15)  {
347 					cturn *= -2;
348 					break;
349 				}
350 				continue;
351 
352 			}
353 
354 							/* (player's move) */
355 
356 							/* clean screen if
357 							 * safe */
358 			if (tflag && hflag)  {
359 				curmove (20,0);
360 				clend ();
361 				hflag = 1;
362 			}
363 
364 							/* if allowed, give him
365 							 * a chance to double */
366 			if (dlast != cturn && gvalue < 64)  {
367 				if (tflag)
368 					curmove (cturn == -1? 18: 19,0);
369 				writel (*Colorptr);
370 				c = readc();
371 
372 							/* character cases */
373 				switch (c)  {
374 
375 							/* reprint board */
376 				case 'R':
377 					wrboard();
378 					break;
379 
380 							/* save game */
381 				case 'S':
382 					raflag = 1;
383 					save (1);
384 					break;
385 
386 							/* quit */
387 				case 'Q':
388 					quit();
389 					break;
390 
391 							/* double */
392 				case 'D':
393 					dble();
394 					break;
395 
396 							/* roll */
397 				case ' ':
398 				case '\n':
399 					roll();
400 					writel (" rolls ");
401 					writec (D0+'0');
402 					writec (' ');
403 					writec (D1+'0');
404 					writel (".  ");
405 
406 							/* see if he can move */
407 					if ( (mvlim = movallow()) == 0)  {
408 
409 							/* can't move */
410 						writel (toobad1);
411 						writel (*colorptr);
412 						writel (unable);
413 						if (tflag)  {
414 							if (pnum)  {
415 								buflush();
416 								sleep (MVPAUSE);
417 							}
418 						}
419 						nexturn();
420 						break;
421 					}
422 
423 							/* get move */
424 					getmove();
425 
426 							/* okay to clean
427 							 * screen */
428 					hflag = 1;
429 					break;
430 
431 							/* invalid character */
432 				default:
433 
434 							/* print help message */
435 					if (tflag)
436 						curmove (20,0);
437 					else
438 						writec ('\n');
439 					text (helpm);
440 					if (tflag)
441 						curmove (cturn == -1? 18: 19,0);
442 					else
443 						writec ('\n');
444 
445 							/* don't erase */
446 					hflag = 0;
447 				}
448 			} else  {			/* couldn't double */
449 
450 							/* print roll */
451 				roll();
452 				if (tflag)
453 					curmove (cturn == -1? 18: 19,0);
454 				proll ();
455 
456 							/* can he move? */
457 				if ((mvlim = movallow()) == 0)  {
458 
459 							/* he can't */
460 					writel (toobad2);
461 					writel (*colorptr);
462 					writel (cantmv);
463 					buflush();
464 					sleep (MVPAUSE);
465 					nexturn();
466 					continue;
467 				}
468 
469 							/* get move */
470 				getmove();
471 			}
472 		}
473 
474 							/* don't worry about who
475 							 * won if quit */
476 		if (cturn == 0)
477 			break;
478 
479 							/* fix cturn = winner */
480 		cturn /= -2;
481 
482 							/* final board pos. */
483 		if (tflag)
484 			refresh();
485 
486 							/* backgammon? */
487 		mflag = 0;
488 		l = bar+7*cturn;
489 		for (i = bar; i != l; i += cturn)
490 			if (board[i]*cturn)  mflag++;
491 
492 							/* compute game value */
493 		if (tflag)
494 			curmove (20,0);
495 		if (*offopp == 15)  {
496 			if (mflag)  {
497 				writel (bgammon);
498 				gvalue *= 3;
499 			}
500 			else  if (*offptr <= 0)  {
501 				writel (gammon);
502 				gvalue *= 2;
503 			}
504 		}
505 
506 							/* report situation */
507 		if (cturn == -1)  {
508 			writel ("Red wins ");
509 			rscore += gvalue;
510 		} else {
511 			writel ("White wins ");
512 			wscore += gvalue;
513 		}
514 		wrint (gvalue);
515 		writel (" point");
516 		if (gvalue > 1)
517 			writec ('s');
518 		writel (".\n");
519 
520 							/* write score */
521 		wrscore();
522 
523 							/* check user count */
524 # ifdef CORY
525 		if (ucount() > MAXUSERS)  {
526 			writel (user2a);
527 			wrint (MAXUSERS);
528 			writel (user2b);
529 			rfl = 1;
530 			break;
531 		}
532 # endif
533 
534 							/* see if he wants
535 							 * another game */
536 		writel (again);
537 		if ((i = yorn ('S')) == 0)
538 			break;
539 
540 		init();
541 		if (i == 2)  {
542 			writel ("  Save.\n");
543 			cturn = 0;
544 			save (0);
545 		}
546 
547 							/* yes, reset game */
548 		wrboard();
549 	}
550 
551 	/* give him a chance to save if game was recovered */
552 	if (rfl && cturn)  {
553 		writel (svpromt);
554 		if (yorn (0))  {
555 							/* re-initialize for
556 							 * recovery */
557 			init();
558 			cturn = 0;
559 			save(0);
560 		}
561 	}
562 
563 							/* leave peacefully */
564 	getout ();
565 }
566