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