1 /* @(#)main.c 8.1 (Berkeley) 5/31/93 */
2 /* $NetBSD: main.c,v 1.33 2019/02/03 10:45:58 mrg Exp $ */
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "backlocal.h"
38 #define MVPAUSE 5 /* time to sleep when stuck */
40 extern const char *const instr
[]; /* text of instructions */
41 extern const char *const message
[]; /* update message */
43 static const char *const helpm
[] = { /* help message */
44 "Enter a space or newline to roll, or",
45 " R to reprint the board\tD to double",
46 " S to save the game\tQ to quit",
50 static const char *const contin
[] = { /* pause message */
51 "(Type a newline to continue.)",
55 static const char rules
[] = "\nDo you want the rules of the game?";
56 static const char noteach
[] = "Teachgammon not available!\n\a";
57 static const char need
[] = "Do you need instructions for this program?";
58 static const char askcol
[] =
59 "Enter 'r' to play red, 'w' to play white, 'b' to play both:";
60 static const char rollr
[] = "Red rolls a ";
61 static const char rollw
[] = ". White rolls a ";
62 static const char rstart
[] = ". Red starts.\n";
63 static const char wstart
[] = ". White starts.\n";
64 static const char toobad1
[] = "Too bad, ";
65 static const char unable
[] = " is unable to use that roll.\n";
66 static const char toobad2
[] = ". Too bad, ";
67 static const char cantmv
[] = " can't move.\n";
68 static const char bgammon
[] = "Backgammon! ";
69 static const char gammon
[] = "Gammon! ";
70 static const char again
[] = ".\nWould you like to play again?";
71 static const char svpromt
[] = "Would you like to save this game?";
73 static const char password
[] = "losfurng";
77 main(int argc __unused
, char **argv
)
79 int i
; /* non-descript index */
80 int l
; /* non-descript index */
81 char c
; /* non-descript character storage */
82 time_t t
; /* time for random num generator */
83 struct move mmstore
, *mm
;
85 /* revoke setgid privileges */
89 bflag
= 2; /* default no board */
90 signal(SIGINT
, getout
); /* trap interrupts */
91 if (tcgetattr(0, &old
) == -1) /* get old tty mode */
92 errexit("backgammon(gtty)");
94 noech
.c_lflag
&= ~ECHO
;
96 raw
.c_lflag
&= ~ICANON
; /* set up modes */
97 ospeed
= cfgetospeed(&old
); /* for termlib */
99 /* get terminal capabilities, and decide if it can cursor address */
100 tflag
= getcaps(getenv("TERM"));
101 /* use whole screen for text */
105 srandom(t
); /* 'random' seed */
107 /* need this now beceause getarg() may try to load a game */
110 while (*++argv
!= 0) /* process arguments */
113 if (tflag
) { /* clear screen */
114 noech
.c_oflag
&= ~(ONLCR
| OXTABS
);
115 raw
.c_oflag
&= ~(ONLCR
| OXTABS
);
118 fixtty(&raw
); /* go into raw mode */
120 /* check if restored game and save flag for later */
121 if ((rfl
= rflag
) != 0) {
122 wrtext(message
); /* print message */
124 wrboard(); /* print board */
125 /* if new game, pretend to be a non-restored game */
129 rscore
= wscore
= 0; /* zero score */
130 wrtext(message
); /* update message without pausing */
132 if (aflag
) { /* print rules */
136 fixtty(&old
); /* restore tty */
137 execl(TEACH
, "teachgammon", args
[0]?args
:0,
140 tflag
= 0; /* error! */
143 } else {/* if not rules, then instructions */
145 if (yorn(0)) { /* print instructions */
151 init(); /* initialize board */
153 if (pnum
== 2) {/* ask for color(s) */
164 case 'W': /* white */
180 signal(SIGALRM
, getout
);
183 for (i
= 0; i
< 10; i
++) {
189 while (readc() != '\n');
194 for (i
= 0; i
< 9; i
++)
195 if (pbuf
[i
] != password
[i
])
211 /* pause to read message */
214 wrboard(); /* print board */
221 /* limit text to bottom of screen */
225 for (;;) { /* begin game! */
226 /* initial roll if needed */
227 if ((!rflag
) || raflag
)
230 /* perform ritual of first roll */
234 while (mm
->D0
== mm
->D1
) /* no doubles */
239 writec(mm
->D0
+ '0');
241 writec(mm
->D1
+ '0');
243 /* winner goes first */
244 if (mm
->D0
> mm
->D1
) {
252 /* initialize variables according to whose turn it is */
254 if (cturn
== 1) { /* red */
261 Colorptr
= &color
[1];
262 colorptr
= &color
[3];
271 Colorptr
= &color
[0];
272 colorptr
= &color
[2];
276 /* do first move (special case) */
277 if (!(rflag
&& raflag
)) {
278 if (cturn
== pnum
) /* computer's move */
280 else { /* player's move */
281 mm
->mvlim
= movallow(mm
);
284 curmove(cturn
== -1 ? 18 : 19, 0);
286 getmove(mm
); /* get player's move */
294 /* no longer any diff- erence between normal game and
298 /* move as long as it's someone's turn */
299 while (cturn
== 1 || cturn
== -1) {
301 /* board maintainence */
303 refresh(); /* fix board */
305 /* redo board if -p */
306 if (cturn
== bflag
|| bflag
== 0)
309 /* do computer's move */
313 /* see if double refused */
314 if (cturn
== -2 || cturn
== 2)
317 /* check for winning move */
325 /* (player's move) */
327 /* clean screen if safe */
328 if (tflag
&& hflag
) {
333 /* if allowed, give him a chance to double */
334 if (dlast
!= cturn
&& gvalue
< 64) {
336 curmove(cturn
== -1 ? 18 : 19, 0);
340 /* character cases */
369 writec(mm
->D0
+ '0');
371 writec(mm
->D1
+ '0');
374 /* see if he can move */
375 if ((mm
->mvlim
= movallow(mm
)) == 0) {
393 /* okay to clean screen */
397 /* invalid character */
400 /* print help message */
407 curmove(cturn
== -1 ?
415 } else {/* couldn't double */
420 curmove(cturn
== -1 ? 18 : 19, 0);
424 if ((mm
->mvlim
= movallow(mm
)) == 0) {
440 /* don't worry about who won if quit */
444 /* fix cturn = winner */
447 /* final board pos. */
454 for (i
= bar
; i
!= l
; i
+= cturn
)
455 if (board
[i
] && cturn
)
458 /* compute game value */
461 if (*offopp
== 15 && (*offptr
== 0 || *offptr
== -15)) {
470 /* report situation */
475 writel("White wins ");
487 /* see if he wants another game */
489 if ((i
= yorn('S')) == 0)
498 /* yes, reset game */
502 /* give him a chance to save if game was recovered */
506 /* re-initialize for recovery */
512 /* leave peacefully */