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