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