BSD 4_3_Reno release
[unix-history] / usr / src / games / backgammon / backgammon / main.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)main.c 5.6 (Berkeley) 6/1/90";
#endif /* not lint */
#include <stdio.h>
#include "back.h"
#define MVPAUSE 5 /* time to sleep when stuck */
#define MAXUSERS 35 /* maximum number of users */
char *instr[]; /* text of instructions */
char *message[]; /* update message */
char ospeed; /* tty output speed */
char *helpm[] = { /* help message */
"Enter a space or newline to roll, or",
" R to reprint the board\tD to double",
" S to save the game\tQ to quit",
0
};
char *contin[] = { /* pause message */
"(Type a newline to continue.)",
"",
0
};
static char user1a[] =
"Sorry, you cannot play backgammon when there are more than ";
static char user1b[] =
" users\non the system.";
static char user2a[] =
"\nThere are now more than ";
static char user2b[] =
" users on the system, so you cannot play\nanother game. ";
static char rules[] = "\nDo you want the rules of the game?";
static char noteach[] = "Teachgammon not available!\n\007";
static char need[] = "Do you need instructions for this program?";
static char askcol[] =
"Enter 'r' to play red, 'w' to play white, 'b' to play both:";
static char rollr[] = "Red rolls a ";
static char rollw[] = ". White rolls a ";
static char rstart[] = ". Red starts.\n";
static char wstart[] = ". White starts.\n";
static char toobad1[] = "Too bad, ";
static char unable[] = " is unable to use that roll.\n";
static char toobad2[] = ". Too bad, ";
static char cantmv[] = " can't move.\n";
static char bgammon[] = "Backgammon! ";
static char gammon[] = "Gammon! ";
static char again[] = ".\nWould you like to play again?";
static char svpromt[] = "Would you like to save this game?";
static char password[] = "losfurng";
static char pbuf[10];
main (argc,argv)
int argc;
char **argv;
{
register int i; /* non-descript index */
register int l; /* non-descript index */
register char c; /* non-descript character storage */
long t; /* time for random num generator */
/* initialization */
bflag = 2; /* default no board */
signal (2,getout); /* trap interrupts */
if (gtty (0,&tty) == -1) /* get old tty mode */
errexit ("backgammon(gtty)");
old = tty.sg_flags;
#ifdef V7
raw = ((noech = old & ~ECHO) | CBREAK); /* set up modes */
#else
raw = ((noech = old & ~ECHO) | RAW); /* set up modes */
#endif
ospeed = tty.sg_ospeed; /* for termlib */
/* check user count */
# ifdef CORY
if (ucount() > MAXUSERS) {
writel (user1a);
wrint (MAXUSERS);
writel (user1b);
getout();
}
# endif
/* get terminal
* capabilities, and
* decide if it can
* cursor address */
tflag = getcaps (getenv ("TERM"));
/* use whole screen
* for text */
if (tflag)
begscr = 0;
t = time(0);
srandom(t); /* 'random' seed */
#ifdef V7
while (*++argv != 0) /* process arguments */
#else
while (*++argv != -1) /* process arguments */
#endif
getarg (&argv);
args[acnt] = '\0';
if (tflag) { /* clear screen */
noech &= ~(CRMOD|XTABS);
raw &= ~(CRMOD|XTABS);
clear();
}
fixtty (raw); /* go into raw mode */
/* check if restored
* game and save flag
* for later */
if (rfl = rflag) {
text (message); /* print message */
text (contin);
wrboard(); /* print board */
/* if new game, pretend
* to be a non-restored
* game */
if (cturn == 0)
rflag = 0;
} else {
rscore = wscore = 0; /* zero score */
text (message); /* update message
* without pausing */
if (aflag) { /* print rules */
writel (rules);
if (yorn(0)) {
fixtty (old); /* restore tty */
execl (TEACH,"teachgammon",args,0);
tflag = 0; /* error! */
writel (noteach);
exit();
} else { /* if not rules, then
* instructions */
writel (need);
if (yorn(0)) { /* print instructions */
clear();
text (instr);
}
}
}
init(); /* initialize board */
if (pnum == 2) { /* ask for color(s) */
writec ('\n');
writel (askcol);
while (pnum == 2) {
c = readc();
switch (c) {
case 'R': /* red */
pnum = -1;
break;
case 'W': /* white */
pnum = 1;
break;
case 'B': /* both */
pnum = 0;
break;
case 'P':
if (iroll)
break;
if (tflag)
curmove (curr,0);
else
writec ('\n');
writel ("Password:");
signal (14,getout);
cflag = 1;
alarm (10);
for (i = 0; i < 10; i++) {
pbuf[i] = readc();
if (pbuf[i] == '\n')
break;
}
if (i == 10)
while (readc() != '\n');
alarm (0);
cflag = 0;
if (i < 10)
pbuf[i] = '\0';
for (i = 0; i < 9; i++)
if (pbuf[i] != password[i])
getout();
iroll = 1;
if (tflag)
curmove (curr,0);
else
writec ('\n');
writel (askcol);
break;
default: /* error */
writec ('\007');
}
}
} else if (!aflag)
/* pause to read
* message */
text (contin);
wrboard(); /* print board */
if (tflag)
curmove (18,0);
else
writec ('\n');
}
/* limit text to bottom
* of screen */
if (tflag)
begscr = 17;
for (;;) { /* begin game! */
/* initial roll if
* needed */
if ((! rflag) || raflag)
roll();
/* perform ritual of
* first roll */
if (! rflag) {
if (tflag)
curmove (17,0);
while (D0 == D1) /* no doubles */
roll();
/* print rolls */
writel (rollr);
writec (D0+'0');
writel (rollw);
writec (D1+'0');
/* winner goes first */
if (D0 > D1) {
writel (rstart);
cturn = 1;
} else {
writel (wstart);
cturn = -1;
}
}
/* initalize variables
* according to whose
* turn it is */
if (cturn == 1) { /* red */
home = 25;
bar = 0;
inptr = &in[1];
inopp = &in[0];
offptr = &off[1];
offopp = &off[0];
Colorptr = &color[1];
colorptr = &color[3];
colen = 3;
} else { /* white */
home = 0;
bar = 25;
inptr = &in[0];
inopp = &in[1];
offptr = &off[0];
offopp = &off[1];
Colorptr = &color[0];
colorptr = &color[2];
colen = 5;
}
/* do first move
* (special case) */
if (! (rflag && raflag)) {
if (cturn == pnum) /* computer's move */
move (0);
else { /* player's move */
mvlim = movallow();
/* reprint roll */
if (tflag)
curmove (cturn == -1? 18: 19,0);
proll();
getmove(); /* get player's move */
}
}
if (tflag) {
curmove (17,0);
cline();
begscr = 18;
}
/* no longer any diff-
* erence between normal
* game and recovered
* game. */
rflag = 0;
/* move as long as it's
* someone's turn */
while (cturn == 1 || cturn == -1) {
/* board maintainence */
if (tflag)
refresh(); /* fix board */
else
/* redo board if -p */
if (cturn == bflag || bflag == 0)
wrboard();
/* do computer's move */
if (cturn == pnum) {
move (1);
/* see if double
* refused */
if (cturn == -2 || cturn == 2)
break;
/* check for winning
* move */
if (*offopp == 15) {
cturn *= -2;
break;
}
continue;
}
/* (player's move) */
/* clean screen if
* safe */
if (tflag && hflag) {
curmove (20,0);
clend ();
hflag = 1;
}
/* if allowed, give him
* a chance to double */
if (dlast != cturn && gvalue < 64) {
if (tflag)
curmove (cturn == -1? 18: 19,0);
writel (*Colorptr);
c = readc();
/* character cases */
switch (c) {
/* reprint board */
case 'R':
wrboard();
break;
/* save game */
case 'S':
raflag = 1;
save (1);
break;
/* quit */
case 'Q':
quit();
break;
/* double */
case 'D':
dble();
break;
/* roll */
case ' ':
case '\n':
roll();
writel (" rolls ");
writec (D0+'0');
writec (' ');
writec (D1+'0');
writel (". ");
/* see if he can move */
if ( (mvlim = movallow()) == 0) {
/* can't move */
writel (toobad1);
writel (*colorptr);
writel (unable);
if (tflag) {
if (pnum) {
buflush();
sleep (MVPAUSE);
}
}
nexturn();
break;
}
/* get move */
getmove();
/* okay to clean
* screen */
hflag = 1;
break;
/* invalid character */
default:
/* print help message */
if (tflag)
curmove (20,0);
else
writec ('\n');
text (helpm);
if (tflag)
curmove (cturn == -1? 18: 19,0);
else
writec ('\n');
/* don't erase */
hflag = 0;
}
} else { /* couldn't double */
/* print roll */
roll();
if (tflag)
curmove (cturn == -1? 18: 19,0);
proll ();
/* can he move? */
if ((mvlim = movallow()) == 0) {
/* he can't */
writel (toobad2);
writel (*colorptr);
writel (cantmv);
buflush();
sleep (MVPAUSE);
nexturn();
continue;
}
/* get move */
getmove();
}
}
/* don't worry about who
* won if quit */
if (cturn == 0)
break;
/* fix cturn = winner */
cturn /= -2;
/* final board pos. */
if (tflag)
refresh();
/* backgammon? */
mflag = 0;
l = bar+7*cturn;
for (i = bar; i != l; i += cturn)
if (board[i]*cturn) mflag++;
/* compute game value */
if (tflag)
curmove (20,0);
if (*offopp == 15) {
if (mflag) {
writel (bgammon);
gvalue *= 3;
}
else if (*offptr <= 0) {
writel (gammon);
gvalue *= 2;
}
}
/* report situation */
if (cturn == -1) {
writel ("Red wins ");
rscore += gvalue;
} else {
writel ("White wins ");
wscore += gvalue;
}
wrint (gvalue);
writel (" point");
if (gvalue > 1)
writec ('s');
writel (".\n");
/* write score */
wrscore();
/* check user count */
# ifdef CORY
if (ucount() > MAXUSERS) {
writel (user2a);
wrint (MAXUSERS);
writel (user2b);
rfl = 1;
break;
}
# endif
/* see if he wants
* another game */
writel (again);
if ((i = yorn ('S')) == 0)
break;
init();
if (i == 2) {
writel (" Save.\n");
cturn = 0;
save (0);
}
/* yes, reset game */
wrboard();
}
/* give him a chance to save if game was recovered */
if (rfl && cturn) {
writel (svpromt);
if (yorn (0)) {
/* re-initialize for
* recovery */
init();
cturn = 0;
save(0);
}
}
/* leave peacefully */
getout ();
}