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