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