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
main(argc,argv)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