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