[comp.sources.games] v03i094: backgammon - 4.3BSD backgammon game, Part01/03

games-request@tekred.TEK.COM (03/10/88)

Submitted by: John Gilmore <hoptoad.UUCP!gnu@cgl.ucsf.edu>
Comp.sources.games: Volume 3, Issue 94
Archive-name: backgammon/Part01


[This is the backgammon game distributed with Berkeley 4.3BSD Unix.
 The game source has been "declassified", which means you no longer
 need a Unix source license to legally have a copy of this.  See the
 copyright notice at the begining of each file for details.  Thanks
 to Kirk McKusick and John Gilmore for making this available.  -br]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  README MANIFEST data.c fancy.c main.c move.c save.c
# Wrapped by billr@saab on Wed Mar  9 09:37:12 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(261 characters\)
sed "s/^X//" >README <<'END_OF_README'
XThis is the backgammon game distributed with Berkeley 4.3BSD Unix.
XThe game source has been "declassified", which means you no longer
Xneed a Unix source license to legally have a copy of this.  See the
Xcopyright notice at the begining of each file for details.
END_OF_README
if test 261 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(894 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                  1	This shipping list
X Makefile                  2	
X README                    1	
X allow.c                   3	
X back.h                    2	
X backgammon.1              2	
X board.c                   3	
X check.c                   3	
X data.c                    1	
X extra.c                   2	
X fancy.c                   1	
X init.c                    3	
X main.c                    1	
X move.c                    1	
X odds.c                    3	
X one.c                     3	
X save.c                    1	
X subs.c                    2	
X table.c                   2	
X teach.c                   3	
X text.c                    2	
X ttext1.c                  2	
X ttext2.c                  2	
X tutor.c                   3	
X tutor.h                   3	
X version.c                 2	
END_OF_MANIFEST
if test 894 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f data.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"data.c\"
else
echo shar: Extracting \"data.c\" \(8647 characters\)
sed "s/^X//" >data.c <<'END_OF_data.c'
X/*
X * Copyright (c) 1980 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)data.c	5.2 (Berkeley) 2/16/88";
X#endif /* not lint */
X
X#include "tutor.h"
X
Xint	maxmoves = 23;
X
Xchar  *text0[] = {
X	"To start the game, I roll a 3, and you roll a 1.  This means",
X	"that I get to start first.  I move 8-5,6-5 since this makes a",
X	"new point and helps to trap your back men on 1.  You should be",
X	"able to do a similar move with your roll.",
X	0
X};
X
Xchar  *text1[] = {
X	"Now you shall see a move using doubles.  I just rolled double",
X	"5's.  I will move two men from position 13 to position 3.  The",
X	"notation for this is 13-8,13-8,8-3,8-3.  You will also roll dou-",
X	"bles, but you will be able to make a much stronger move.",
X	0
X};
X
Xchar  *text2[] = {
X	"Excellent!  As you can see, you are beginning to develop a wall",
X	"which is trapping my men on position 24.  Also, moving your back",
X	"men forward not only improves your board position safely, but it",
X	"thwarts my effort to make a wall.",
X	"",
X	"My roll now is 5 6.  Normally, I would use that roll to move from",
X	"position 24 to position 13 (24-18-13), but your new point prevents",
X	"that.  Instead, I am forced to move from 13 to 2, where my man is",
X	"open but cannot be hit.",
X	0
X};
X
Xchar  *text3[] = {
X	"As you can see, although you left a man open, it is a rela-",
X	"tively safe move to an advantageous position, which might help",
X	"you make a point later.  Only two rolls (4 5 or 5 4) will allow",
X	"me to hit you.  With an unprecedented amount of luck, I happen",
X	"to roll a 4 5 and hit you as just mentioned.",
X	0
X};
X
Xchar  *text4[] = {
X	"You're pretty lucky yourself, you know.  I follow by rolling 2 3",
X	"and moving 25-22,24-22, forming a new point.",
X	0
X};
X
Xchar  *text5[] = {
X	"Not a spectacular move, but a safe one.  I follow by rolling 6 1.",
X	"I decide to use this roll to move 22-16,16-17.  It leaves me with",
X	"one man still open, but the blot is farther back on the board, and",
X	"would suffer less of a loss by being hit.",
X	0
X};
X
Xchar  *text6[] = {
X	"By moving your two men from 17 to 20, you lessen my chance of",
X	"getting my man off the board.  In fact, the odds are 5 to 4",
X	"against me getting off.  I roll with the odds and helplessly",
X	"receive a 3 5.",
X	0
X};
X
Xchar  *text7[] = {
X	"Note that the blot on 7 cannot be hit unless I get off the bar",
X	"and have a 1 or a 6 left over, and doing so will leave two of",
X	"my men open.  Also, the blot on 16 cannot be hit at all!  With",
X	"a sigh of frustration, I roll double 6's and remain immobile.",
X	0
X};
X
Xchar  *text8[] = {
X	"See, you did not get hit and, you got to 'cover up' your open men.",
X	"Quite an accomplishment.  Finally, I get off the bar by rolling",
X	"6 2 and moving 25-23,23-17.",
X	0
X};
X
Xchar  *text9[] = {
X	"My venture off the bar did not last long.  However, I got lucky",
X	"and rolled double 1's, allowing me to move 0-1,1-2,15-14,15-14.",
X	0
X};
X
Xchar  *text10[] = {
X	"You are improving your position greatly and safely, and are well",
X	"on the way to winning the game.  I roll a 6 2 and squeak past",
X	"your back man.  Now the game becomes a race to the finish.",
X	0
X};
X
Xchar  *text11[] = {
X	"Now that it is merely a race, you are trying to get as many men",
X	"as possible into the inner table, so you can start removing them.",
X	"I roll a 3 4 and move my two men farthest back to position 11",
X	"(15-11,14-11).",
X	0
X};
X
Xchar  *text12[] = {
X	"The race is still on, and you have seem to be doing all right.",
X	"I roll 6 1 and move 14-8,13-12.",
X	0
X};
X
Xchar  *text13[] = {
X	"Notice that you get to remove men the instant you have all of",
X	"them at your inner table, even if it is the middle of a turn.",
X	"I roll 1 2 and move 13-11,12-11.",
X	0
X};
X
Xchar  *text14[] = {
X	"Although you could have removed a man, this move illustrates two",
X	"points:  1) You never have to remove men, and 2) You should try",
X	"to spread out your men on your inner table.  Since you have one",
X	"man on each position, you should be able to remove at least two",
X	"men next turn.  I roll 2 5 and move 8-6,11-6.",
X	0
X};
X
Xchar  *text15[] = {
X	"This time you were able to remove men.  I roll 3 4 and move",
X	"11-7,11-8.  The race continues.",
X	0
X};
X
Xchar  *text16[] = {
X	"More holes are opening up in your inner table, but you are",
X	"still very much ahead.  If we were doubling, you would have",
X	"doubled long ago.  I roll 2 6 and move 8-6,11-5.",
X	0
X};
X
Xchar  *text17[] = {
X	"It pays to spread out your men.  I roll 3 5 and move 7-4,8-3.",
X	0
X};
X
Xchar  *text18[] = {
X	"You can only remove some men, but you spread out more and",
X	"more, in order to be able to remove men more efficiently.",
X	"I roll double 3's, which help, but not that much.  I move",
X	"8-5,3-0,3-0,3-0.",
X	0
X};
X
Xchar  *text19[] = {
X	"I roll 1 4 and move 5-4,4-0.",
X	0
X};
X
Xchar  *text20[] = {
X	"You are now nicely spread out to win a game.  I roll 5 6 and",
X	"move 5-0,6-0.",
X	0
X};
X
Xchar  *text21[] = {
X	"Any minute now.  Just a few short steps from victory.  I roll",
X	"2 4 and move 6-4,4-0.",
X	0
X};
X
Xchar  *text22[] = {
X	"It looks pretty hopeless for me, but I play on, rolling 1 3 and",
X	"moving 4-3,3-0.",
X	0
X};
X
Xchar  *text23[] = {
X	"Congratulations!  You just won a game of backgammon against the",
X	"computer!  You will now be able to play a game, but remember,",
X	"when you start playing, that doubling will be enabled, which",
X	"will add another factor to the game...  Good luck!!",
X	"",
X	0
X};
X
Xstruct situatn  test[] = {
X	{
X		{0,2,0,0,0,0,-5,0,-3,0,0,0,5,-5,0,0,0,3,0,5,0,0,0,0,-2,0},
X		3, 1, {8,6,0,0}, {5,5,0,0}, 4, 2, text0
X	},
X	{
X		{0,2,0,0,0,-2,-4,0,-2,0,0,0,5,-5,0,0,0,2,0,4,0,2,0,0,-2,0},
X		5, 5, {13,13,8,8}, {8,8,3,3}, 6, 6, text1
X	},
X	{
X		{0,0,0,-2,0,-2,-4,2,-2,0,0,0,3,-3,0,0,0,2,2,4,0,2,0,0,-2,0},
X		6, 5, {13,8,0,0}, {8,2,0,0}, 1, 2, text2
X	},
X	{
X		{0,0,-1,-2,0,-2,-4,2,-2,0,0,0,2,-2,0,1,0,2,2,4,0,2,0,0,-2,0},
X		4, 5, {24,20,0,0}, {20,15,0,0}, 2, 5, text3
X	},
X	{
X		{0,0,0,-2,0,-2,-4,3,-2,0,0,0,2,-2,0,-1,0,2,2,4,0,2,0,0,-1,-1},
X		2, 3, {25,24,0,0}, {22,22,0,0}, 4, 1, text4
X	},
X	{
X		{0,0,0,-2,0,-2,-4,2,-2,0,0,0,3,-2,0,-1,0,2,2,4,0,2,-2,0,0,0},
X		6, 1, {22,16,0,0}, {16,15,0,0}, 3, 3, text5
X	},
X	{
X		{0,0,0,-2,0,-2,-4,2,-2,0,0,0,3,-2,0,-2,0,0,2,2,2,2,2,0,0,-1},
X		3, 5, {0,0,0,0}, {0,0,0,0}, 5, 4, text6
X	},
X	{
X		{0,0,0,-2,0,-2,-4,1,-2,0,0,0,3,-2,0,-2,1,0,2,2,2,2,2,0,0,-1},
X		6, 6, {0,0,0,0}, {0,0,0,0}, 3, 6, text7
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-2,0,0,0,3,-2,0,-2,2,0,2,2,2,2,2,0,0,-1},
X		2, 6, {25,23,0,0}, {23,17,0,0}, 5, 1, text8
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-2,0,0,0,2,-2,0,-2,2,0,3,2,2,2,2,0,0,-1},
X		1, 1, {25,24,15,15}, {24,23,14,14}, 4, 6, text9
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-2,0,0,0,0,-2,-2,0,3,0,4,2,2,2,2,-1,0,0},
X		6, 2, {23,17,0,0}, {17,15,0,0}, 1, 3, text10
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-2,0,0,0,0,-2,-2,-1,2,0,3,4,2,2,2,0,0,0},
X		4, 3, {15,14,0,0}, {11,11,0,0}, 5, 3, text11
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-2,0,0,-2,0,-2,-1,0,0,0,3,5,2,3,2,0,0,0},
X		6, 1, {14,13,0,0}, {8,12,0,0}, 4, 4, text12
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-3,0,0,-2,-1,-1,0,0,0,0,0,5,2,2,5,0,0,0},
X		2, 1, {13,12,0,0}, {11,11,0,0}, 2, 1, text13
X	},
X	{
X		{0,0,0,-2,0,-2,-4,0,-3,0,0,-4,0,0,0,0,0,0,0,5,2,2,3,1,1,0},
X		2, 5, {8,11,0,0}, {6,6,0,0}, 6, 3, text14
X	},
X	{
X		{0,0,0,-2,0,-2,-6,0,-2,0,0,-3,0,0,0,0,0,0,0,4,2,2,2,1,1,0},
X		4, 3, {11,11,0,0}, {7,8,0,0}, 2, 5, text15
X	},
X	{
X		{0,0,0,-2,0,-2,-6,-1,-3,0,0,-1,0,0,0,0,0,0,0,4,1,2,2,0,1,0},
X		2, 6, {8,11,0,0}, {6,5,0,0}, 6, 1, text16
X	},
X	{
X		{0,0,0,-2,0,-3,-7,-1,-2,0,0,0,0,0,0,0,0,0,0,3,1,2,2,0,0,0},
X		5, 3, {8,7,0,0}, {3,4,0,0}, 5, 2, text17
X	},
X	{
X		{0,0,0,-3,-1,-3,-7,0,-1,0,0,0,0,0,0,0,0,0,0,3,0,1,2,1,0,0},
X		3, 3, {8,3,3,3}, {5,0,0,0}, 1, 6, text18
X	},
X	{
X		{0,0,0,0,-1,-4,-7,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,1,0,0},
X		1, 4, {4,5,0,0}, {0,4,0,0}, 2, 3, text19
X	},
X	{
X		{0,0,0,0,-1,-3,-7,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0},
X		5, 6, {6,5,0,0}, {0,0,0,0}, 1, 4, text20
X	},
X	{
X		{0,0,0,0,-1,-2,-6,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0},
X		2, 4, {4,6,0,0}, {0,4,0,0}, 6, 2, text21
X	},
X	{
X		{0,0,0,0,-1,-2,-5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0},
X		3, 1, {4,3,0,0}, {3,0,0,0}, 4, 3, text22
X	},
X	{
X		{0,0,0,0,0,-2,-5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
X		0, 0, {0,0,0,0}, {0,0,0,0}, 0, 0, text23
X	}
X};
END_OF_data.c
if test 8647 -ne `wc -c <data.c`; then
    echo shar: \"data.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fancy.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fancy.c\"
else
echo shar: Extracting \"fancy.c\" \(15617 characters\)
sed "s/^X//" >fancy.c <<'END_OF_fancy.c'
X/*
X * Copyright (c) 1980 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)fancy.c	5.3 (Berkeley) 2/16/88";
X#endif /* not lint */
X
X#include "back.h"
X
Xchar	PC;			/* padding character */
Xchar	*BC;			/* backspace sequence */
Xchar	*CD;			/* clear to end of screen sequence */
Xchar	*CE;			/* clear to end of line sequence */
Xchar	*CL;			/* clear screen sequence */
Xchar	*CM;			/* cursor movement instructions */
Xchar	*HO;			/* home cursor sequence */
Xchar	*MC;			/* column cursor movement map */
Xchar	*ML;			/* row cursor movement map */
Xchar	*ND;			/* forward cursor sequence */
Xchar	*UP;			/* up cursor sequence */
X
Xint	lHO;			/* length of HO */
Xint	lBC;			/* length of BC */
Xint	lND;			/* length of ND */
Xint	lUP;			/* length of UP */
Xint	CO;			/* number of columns */
Xint	LI;			/* number of lines */
Xint	*linect;		/* array of lengths of lines on screen
X				   (the actual screen is not stored) */
X
X				/* two letter codes */
Xchar	tcap[] = "bccdceclcmhomcmlndup";
X				/* corresponding strings */
Xchar	**tstr[] = { &BC, &CD, &CE, &CL, &CM, &HO, &MC, &ML, &ND, &UP };
X
Xint	buffnum;		/* pointer to output buffer */
X
Xchar	tbuf[1024];		/* buffer for decoded termcap entries */
X
Xint	oldb[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
X
Xint	oldr;
Xint	oldw;
X						/* "real" cursor positions, so
X						 * it knows when to reposition.
X						 * These are -1 if curr and curc
X						 * are accurate */
Xint	realr;
Xint	realc;
X
Xvoid	addbuf();
X
Xfboard ()  {
X	register int	i, j, l;
X
X	curmove (0,0);				/* do top line */
X	for (i = 0; i < 53; i++)
X		fancyc ('_');
X
X	curmove (15,0);				/* do botttom line */
X	for (i = 0; i < 53; i++)
X		fancyc ('_');
X
X	l = 1;					/* do vertical lines */
X	for (i = 52; i > -1; i -= 28)  {
X		curmove ( (l == 1? 1: 15) ,i);
X		fancyc ('|');
X		for (j = 0; j < 14; j++)  {
X			curmove (curr+l,curc-1);
X			fancyc ('|');
X		}
X		if (i == 24)
X			i += 32;
X		l = -l;				/* alternate directions */
X	}
X
X	curmove (2,1);				/* label positions 13-18 */
X	for (i = 13; i < 18; i++)  {
X		fancyc ('1');
X		fancyc ((i % 10)+'0');
X		curmove (curr,curc+2);
X	}
X	fancyc ('1');
X	fancyc ('8');
X
X	curmove (2,29);				/* label positions 19-24 */
X	fancyc ('1');
X	fancyc ('9');
X	for (i = 20; i < 25; i++)  {
X		curmove (curr,curc+2);
X		fancyc ('2');
X		fancyc ((i % 10)+'0');
X	}
X
X	curmove (14,1);				/* label positions 12-7 */
X	fancyc ('1');
X	fancyc ('2');
X	for (i = 11; i > 6; i--)  {
X		curmove (curr,curc+2);
X		fancyc (i > 9? '1': ' ');
X		fancyc ((i % 10)+'0');
X	}
X
X	curmove (14,30);			/* label positions 6-1 */
X	fancyc ('6');
X	for (i = 5; i > 0; i--) {
X		curmove (curr,curc+3);
X		fancyc (i+'0');
X	}
X
X	for (i = 12; i > 6; i--)		/* print positions 12-7 */
X		if (board[i])
X			bsect (board[i],13,1+4*(12-i),-1);
X
X	if (board[0])				/* print red men on bar */
X		bsect (board[0],13,25,-1);
X
X	for (i = 6; i > 0; i--)			/* print positions 6-1 */
X		if (board[i])
X			bsect (board[i],13,29+4*(6-i),-1);
X
X	l = (off[1] < 0? off[1]+15: off[1]);	/* print white's home */
X	bsect (l,3,54,1);
X
X	curmove (8,25);				/* print the word BAR */
X	fancyc ('B');
X	fancyc ('A');
X	fancyc ('R');
X
X	for (i = 13; i < 19; i++)		/* print positions 13-18 */
X		if (board[i])
X			bsect (board[i],3,1+4*(i-13),1);
X
X	if (board[25])				/* print white's men on bar */
X		bsect (board[25],3,25,1);
X
X	for (i = 19; i < 25; i++)		/* print positions 19-24 */
X		if (board[i])
X			bsect (board[i],3,29+4*(i-19),1);
X
X	l = (off[0] < 0? off[0]+15: off[0]);	/* print red's home */
X	bsect (-l,13,54,-1);
X
X	for (i = 0; i < 26; i++)		/* save board position
X						 * for refresh later */
X		oldb[i] = board[i];
X	oldr = (off[1] < 0? off[1]+15: off[1]);
X	oldw = -(off[0] < 0? off[0]+15: off[0]);
X}
X
X/*
X * bsect (b,rpos,cpos,cnext)
X *	Print the contents of a board position.  "b" has the value of the
X * position, "rpos" is the row to start printing, "cpos" is the column to
X * start printing, and "cnext" is positive if the position starts at the top
X * and negative if it starts at the bottom.  The value of "cpos" is checked
X * to see if the position is a player's home, since those are printed
X * differently.
X */
X
Xbsect (b,rpos,cpos,cnext)
Xint	b;					/* contents of position */
Xint	rpos;					/* row of position */
Xint	cpos;					/* column of position */
Xint	cnext;					/* direction of position */
X
X{
X	register int	j;			/* index */
X	register int	n;			/* number of men on position */
X	register int	bct;			/* counter */
X	int		k;			/* index */
X	char		pc;			/* color of men on position */
X
X	n = abs(b);				/* initialize n and pc */
X	pc = (b > 0? 'r': 'w');
X
X	if (n < 6 && cpos < 54)			/* position cursor at start */
X		curmove (rpos,cpos+1);
X	else
X		curmove (rpos,cpos);
X
X	for (j = 0; j < 5; j++)  {		/* print position row by row */
X
X		for (k = 0; k < 15; k += 5)		/* print men */
X			if (n > j+k)
X				fancyc (pc);
X
X		if (j < 4)  {				/* figure how far to
X							 * back up for next
X							 * row */
X			if (n < 6)  {			/* stop if none left */
X				if (j+1 == n)
X					break;
X				bct = 1;		/* single column */
X			} else  {
X				if (n < 11)  {		/* two columns */
X					if (cpos == 54)  {	/* home pos */
X						if (j+5 >= n)
X							bct = 1;
X						else
X							bct = 2;
X					}
X					if (cpos < 54)  {	/* not home */
X						if (j+6 >= n)
X							bct = 1;
X						else
X							bct = 2;
X					}
X				} else  {		/* three columns */
X					if (j+10 >= n)
X						bct = 2;
X					else
X						bct = 3;
X				}
X			}
X			curmove (curr+cnext,curc-bct);	/* reposition cursor */
X		}
X	}
X}
X
Xrefresh()  {
X	register int	i, r, c;
X
X	r = curr;				/* save current position */
X	c = curc;
X
X	for (i = 12; i > 6; i--)		/* fix positions 12-7 */
X		if (board[i] != oldb[i])  {
X			fixpos (oldb[i],board[i],13,1+(12-i)*4,-1);
X			oldb[i] = board[i];
X		}
X
X	if (board[0] != oldb[0])  {		/* fix red men on bar */
X		fixpos (oldb[0],board[0],13,25,-1);
X		oldb[0] = board[0];
X	}
X
X	for (i = 6; i > 0; i--)			/* fix positions 6-1 */
X		if (board[i] != oldb[i])  {
X			fixpos (oldb[i],board[i],13,29+(6-i)*4,-1);
X			oldb[i] = board[i];
X		}
X
X	i = -(off[0] < 0? off[0]+15: off[0]);	/* fix white's home */
X	if (oldw != i)  {
X		fixpos (oldw,i,13,54,-1);
X		oldw = i;
X	}
X
X	for (i = 13; i < 19; i++)		/* fix positions 13-18 */
X		if (board[i] != oldb[i])  {
X			fixpos (oldb[i],board[i],3,1+(i-13)*4,1);
X			oldb[i] = board[i];
X		}
X
X	if (board[25] != oldb[25])  {		/* fix white men on bar */
X		fixpos (oldb[25],board[25],3,25,1);
X		oldb[25] = board[25];
X	}
X
X	for (i = 19; i < 25; i++)		/* fix positions 19-24 */
X		if (board[i] != oldb[i])  {
X			fixpos (oldb[i],board[i],3,29+(i-19)*4,1);
X			oldb[i] = board[i];
X		}
X
X	i = (off[1] < 0? off[1]+15: off[1]);	/* fix red's home */
X	if (oldr != i)  {
X		fixpos (oldr,i,3,54,1);
X		oldr = i;
X	}
X
X	curmove (r,c);				/* return to saved position */
X	newpos();
X	buflush();
X}
X
Xfixpos (old,new,r,c,inc)
Xint	old, new, r, c, inc;
X
X{
X	register int	o, n, nv;
X	int		ov, nc;
X	char		col;
X
X	if (old*new >= 0)  {
X		ov = abs(old);
X		nv = abs(new);
X		col = (old+new > 0? 'r': 'w');
X		o = (ov-1)/5;
X		n = (nv-1)/5;
X		if (o == n)  {
X			if (o == 2)
X				nc = c+2;
X			if (o == 1)
X				nc = c < 54? c: c+1;
X			if (o == 0)
X				nc = c < 54? c+1: c;
X			if (ov > nv)
X				fixcol (r+inc*(nv-n*5),nc,abs(ov-nv),' ',inc);
X			else
X				fixcol (r+inc*(ov-o*5),nc,abs(ov-nv),col,inc);
X			return;
X		} else  {
X			if (c < 54)  {
X				if (o+n == 1)  {
X					if (n)  {
X						fixcol (r,c,abs(nv-5),col,inc);
X						if (ov != 5)
X							fixcol (r+inc*ov,c+1,abs(ov-5),col,inc);
X					} else  {
X						fixcol (r,c,abs(ov-5),' ',inc);
X						if (nv != 5)
X							fixcol (r+inc*nv,c+1,abs(nv-5),' ',inc);
X					}
X					return;
X				}
X				if (n == 2)  {
X					if (ov != 10)
X						fixcol (r+inc*(ov-5),c,abs(ov-10),col,inc);
X					fixcol (r,c+2,abs(nv-10),col,inc);
X				} else  {
X					if (nv != 10)
X						fixcol (r+inc*(nv-5),c,abs(nv-10),' ',inc);
X					fixcol (r,c+2,abs(ov-10),' ',inc);
X				}
X				return;
X			}
X			if (n > o)  {
X				fixcol (r+inc*(ov%5),c+o,abs(5*n-ov),col,inc);
X				if (nv != 5*n)
X					fixcol (r,c+n,abs(5*n-nv),col,inc);
X			} else  {
X				fixcol (r+inc*(nv%5),c+n,abs(5*n-nv),' ',inc);
X				if (ov != 5*o)
X					fixcol (r,c+o,abs(5*o-ov),' ',inc);
X			}
X			return;
X		}
X	}
X	nv = abs(new);
X	fixcol (r,c+1,nv,new > 0? 'r': 'w',inc);
X	if (abs(old) <= abs(new))
X		return;
X	fixcol (r+inc*new,c+1,abs(old+new),' ',inc);
X}
X
Xfixcol (r,c,l,ch,inc)
Xregister int	l, ch;
Xint		r, c, inc;
X
X{
X	register int	i;
X
X	curmove (r,c);
X	fancyc (ch);
X	for (i = 1; i < l; i++)  {
X		curmove (curr+inc,curc-1);
X		fancyc (ch);
X	}
X}
X
Xcurmove (r,c)
Xregister int	r, c;
X
X{
X	if (curr == r && curc == c)
X		return;
X	if (realr == -1)  {
X		realr = curr;
X		realc = curc;
X	}
X	curr = r;
X	curc = c;
X}
X
Xnewpos ()  {
X	register int	r;		/* destination row */
X	register int	c;		/* destination column */
X	register int	mode = -1;	/* mode of movement */
X
X	int	count = 1000;		/* character count */
X	int	i;			/* index */
X	int	j;			/* index */
X	int	n;			/* temporary variable */
X	char	*m;			/* string containing CM movement */
X
X
X	if (realr == -1)		/* see if already there */
X		return;
X
X	r = curr;			/* set current and dest. positions */
X	c = curc;
X	curr = realr;
X	curc = realc;
X
X					/* double check position */
X	if (curr == r && curc == c)  {
X		realr = realc = -1;
X		return;
X	}
X
X	if (CM)  {			/* try CM to get there */
X		mode = 0;
X		m = (char *)tgoto (CM,c,r);
X		count = strlen (m);
X	}
X
X					/* try HO and local movement */
X	if (HO && (n = r+c*lND+lHO) < count)  {
X		mode = 1;
X		count = n;
X	}
X
X					/* try various LF combinations */
X	if (r >= curr)  {
X						/* CR, LF, and ND */
X		if ((n = (r-curr)+c*lND+1) < count)  {
X			mode = 2;
X			count = n;
X		}
X						/* LF, ND */
X		if (c >= curc && (n = (r-curr)+(c-curc)*lND) < count)  {
X			mode = 3;
X			count = n;
X		}
X						/* LF, BS */
X		if (c < curc && (n = (r-curr)+(curc-c)*lBC) < count)  {
X			mode = 4;
X			count = n;
X		}
X	}
X
X					/* try corresponding UP combinations */
X	if (r < curr)  {
X						/* CR, UP, and ND */
X		if ((n = (curr-r)*lUP+c*lND+1) < count)  {
X			mode = 5;
X			count = n;
X		}
X						/* UP and ND */
X		if (c >= curc && (n = (curr-r)*lUP+(c-curc)*lND) < count)  {
X			mode = 6;
X			count = n;
X		}
X						/* UP and BS */
X		if (c < curc && (n = (curr-r)*lUP+(curc-c)*lBC) < count)  {
X			mode = 7;
X			count = n;
X		}
X	}
X
X						/* space over */
X	if (curr == r && c > curc && linect[r] < curc && c-curc < count)
X		mode = 8;
X
X	switch (mode)  {
X
X	case -1:				/* error! */
X		write (2,"\r\nInternal cursor error.\r\n",26);
X		getout();
X
X						/* direct cursor motion */
X	case  0:
X		tputs (m,abs(curr-r),addbuf);
X		break;
X
X						/* relative to "home" */
X	case  1:
X		tputs (HO,r,addbuf);
X		for (i = 0; i < r; i++)
X			addbuf ('\012');
X		for (i = 0; i < c; i++)
X			tputs (ND,1,addbuf);
X		break;
X
X						/* CR and down and over */
X	case  2:
X		addbuf ('\015');
X		for (i = 0; i < r-curr; i++)
X			addbuf ('\012');
X		for (i = 0; i < c; i++)
X			tputs (ND,1,addbuf);
X		break;
X	
X						/* down and over */
X	case  3:
X		for (i = 0; i < r-curr; i++)
X			addbuf ('\012');
X		for (i = 0; i < c-curc; i++)
X			tputs (ND,1,addbuf);
X		break;
X	
X						/* down and back */
X	case  4:
X		for (i = 0; i < r-curr; i++)
X			addbuf ('\012');
X		for (i = 0; i < curc-c; i++)
X			addbuf ('\010');
X		break;
X	
X						/* CR and up and over */
X	case  5:
X		addbuf ('\015');
X		for (i = 0; i < curr-r; i++)
X			tputs (UP,1,addbuf);
X		for (i = 0; i < c; i++)
X			tputs (ND,1,addbuf);
X		break;
X	
X						/* up and over */
X	case  6:
X		for (i = 0; i < curr-r; i++)
X			tputs (UP,1,addbuf);
X		for (i = 0; i < c-curc; i++)
X			tputs (ND,1,addbuf);
X		break;
X	
X						/* up and back */
X	case  7:
X		for (i = 0; i < curr-r; i++)
X			tputs (UP,1,addbuf);
X		for (i = 0; i < curc-c; i++)  {
X			if (BC)
X				tputs (BC,1,addbuf);
X			else
X				addbuf ('\010');
X		}
X		break;
X
X						/* safe space */
X	case  8:
X		for (i = 0; i < c-curc; i++)
X			addbuf (' ');
X	}
X
X						/* fix positions */
X	curr = r;
X	curc = c;
X	realr = -1;
X	realc = -1;
X}
X
Xclear ()  {
X	register int	i;
X
X					/* double space if can't clear */
X	if (CL == 0)  {
X		writel ("\n\n");
X		return;
X	}
X
X	curr = curc = 0;		/* fix position markers */
X	realr = realc = -1;
X	for (i = 0; i < 24; i++)	/* clear line counts */
X		linect[i] = -1;
X	buffnum = -1;			/* ignore leftover buffer contents */
X	tputs (CL,CO,addbuf);		/* put CL in buffer */
X}
X
Xtos ()  {				/* home cursor */
X	curmove (0,0);
X}
X
Xfancyc (c)
Xregister char	c;			/* character to output */
X{
X	register int	sp;		/* counts spaces in a tab */
X
X	if (c == '\007')  {		/* bells go in blindly */
X		addbuf (c);
X		return;
X	}
X
X					/* process tabs, use spaces if the
X					 * the tab should be erasing things,
X					 * otherwise use cursor movement
X					 * routines.  Note this does not use
X					 * hardware tabs at all. */
X	if (c == '\t')  {
X		sp = (curc+8) & (~ 7);		/* compute spaces */
X						/* check line length */
X		if (linect[curr] >= curc || sp < 4)  {
X			for (; sp > curc; sp--)
X				addbuf (' ');
X			curc = sp;		/* fix curc */
X		} else
X			curmove (curr,sp);
X		return;
X	}
X
X					/* do newline be calling newline */
X	if (c == '\n')  {
X		newline();
X		return;
X	}
X
X					/* ignore any other control chars */
X	if (c < ' ')
X		return;
X
X					/* if an erasing space or non-space,
X					 * just add it to buffer.  Otherwise
X					 * use cursor movement routine, so that
X					 * multiple spaces will be grouped
X					 * together */
X	if (c > ' ' || linect[curr] >= curc)  {
X		newpos ();			/* make sure position correct */
X		addbuf (c);			/* add character to buffer */
X						/* fix line length */
X		if (c == ' ' && linect[curr] == curc)
X			linect[curr]--;
X		else if (linect[curr] < curc)
X			linect[curr] = curc;
X		curc++;				/* fix curc */
X	} else
X					/* use cursor movement routine */
X		curmove (curr,curc+1);
X}
X
Xclend()  {
X	register int	i;
X	register char	*s;
X
X
X	if (CD)  {
X		tputs (CD,CO-curr,addbuf);
X		for (i = curr; i < LI; i++)
X			linect[i] = -1;
X		return;
X	}
X
X	curmove (i = curr,0);
X	cline();
X	while (curr < LI-1)  {
X		curmove (curr+1,0);
X		if (linect[curr] > -1)
X			cline ();
X	}
X	curmove (i,0);
X}
X
Xcline ()  {
X	register int	i;
X	register int	c;
X	register char	*s;
X
X	if (curc > linect[curr])
X		return;
X	newpos ();
X	if (CE)  {
X		tputs (CE,1,addbuf);
X		linect[curr] = curc-1;
X	} else  {
X		c = curc-1;
X		while (linect[curr] > c)  {
X			addbuf (' ');
X			curc++;
X			linect[curr]--;
X		}
X		curmove (curr,c+1);
X	}
X}
X
Xnewline ()  {
X	cline();
X	if (curr == LI-1)
X		curmove (begscr,0);
X	else
X		curmove (curr+1,0);
X}
X
Xgetcaps (s)
Xregister char	*s;
X
X{
X	register char	*code;		/* two letter code */
X	register char	***cap;		/* pointer to cap string */
X	char		*bufp;		/* pointer to cap buffer */
X	char		tentry[1024];	/* temporary uncoded caps buffer */
X
X	tgetent (tentry,s);		/* get uncoded termcap entry */
X
X	LI = tgetnum ("li");		/* get number of lines */
X	if (LI == -1)
X		LI = 12;
X	CO = tgetnum ("co");		/* get number of columns */
X	if (CO == -1)
X		CO = 65;
X
X	bufp = tbuf;			/* get padding character */
X	tgetstr ("pc",&bufp);
X	if (bufp != tbuf)
X		PC = *tbuf;
X	else
X		PC = 0;
X
X	bufp = tbuf;			/* get string entries */
X	cap = tstr;
X	for (code = tcap; *code; code += 2)
X		**cap++ = (char *)tgetstr (code,&bufp);
X
X					/* get pertinent lengths */
X	if (HO)
X		lHO = strlen (HO);
X	if (BC)
X		lBC = strlen (BC);
X	else
X		lBC = 1;
X	if (UP)
X		lUP = strlen (UP);
X	if (ND)
X		lND = strlen (ND);
X	if (LI < 24 || CO < 72 || !(CL && UP && ND))
X		return (0);
X	linect = (int *)calloc (LI+1,sizeof(int));
X	return (1);
X}
END_OF_fancy.c
if test 15617 -ne `wc -c <fancy.c`; then
    echo shar: \"fancy.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"main.c\"
else
echo shar: Extracting \"main.c\" \(11532 characters\)
sed "s/^X//" >main.c <<'END_OF_main.c'
X/*
X * Copyright (c) 1980 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1980 Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)main.c	5.4 (Berkeley) 2/16/88";
X#endif /* not lint */
X
X#include <stdio.h>
X#include "back.h"
X
X#define MVPAUSE	5				/* time to sleep when stuck */
X#define MAXUSERS 35				/* maximum number of users */
X
Xchar	*instr[];				/* text of instructions */
Xchar	*message[];				/* update message */
Xchar	ospeed;					/* tty output speed */
X
Xchar	*helpm[] = {				/* help message */
X	"Enter a space or newline to roll, or",
X	"     R   to reprint the board\tD   to double",
X	"     S   to save the game\tQ   to quit",
X	0
X};
X
Xchar	*contin[] = {				/* pause message */
X	"(Type a newline to continue.)",
X	"",
X	0
X};
X
Xstatic char user1a[] =
X	"Sorry, you cannot play backgammon when there are more than ";
Xstatic char user1b[] =
X	" users\non the system.";
Xstatic char user2a[] =
X	"\nThere are now more than ";
Xstatic char user2b[] =
X	" users on the system, so you cannot play\nanother game.  ";
Xstatic char	rules[] = "\nDo you want the rules of the game?";
Xstatic char	noteach[] = "Teachgammon not available!\n\007";
Xstatic char	need[] = "Do you need instructions for this program?";
Xstatic char	askcol[] =
X	"Enter 'r' to play red, 'w' to play white, 'b' to play both:";
Xstatic char	rollr[] = "Red rolls a ";
Xstatic char	rollw[] = ".  White rolls a ";
Xstatic char	rstart[] = ".  Red starts.\n";
Xstatic char	wstart[] = ".  White starts.\n";
Xstatic char	toobad1[] = "Too bad, ";
Xstatic char	unable[] = " is unable to use that roll.\n";
Xstatic char	toobad2[] = ".  Too bad, ";
Xstatic char	cantmv[] = " can't move.\n";
Xstatic char	bgammon[] = "Backgammon!  ";
Xstatic char	gammon[] = "Gammon!  ";
Xstatic char	again[] = ".\nWould you like to play again?";
Xstatic char	svpromt[] = "Would you like to save this game?";
X
Xstatic char	password[] = "losfurng";
Xstatic char	pbuf[10];
X
Xmain (argc,argv)
Xint	argc;
Xchar	**argv;
X
X{
X	register int	i;		/* non-descript index */
X	register int	l;		/* non-descript index */
X	register char	c;		/* non-descript character storage */
X	long	t;			/* time for random num generator */
X
X	/* initialization */
X	bflag = 2;					/* default no board */
X	signal (2,getout);				/* trap interrupts */
X	if (gtty (0,&tty) == -1)			/* get old tty mode */
X		errexit ("backgammon(gtty)");
X	old = tty.sg_flags;
X#ifdef V7
X	raw = ((noech = old & ~ECHO) | CBREAK);		/* set up modes */
X#else
X	raw = ((noech = old & ~ECHO) | RAW);		/* set up modes */
X#endif
X	ospeed = tty.sg_ospeed;				/* for termlib */
X
X							/* check user count */
X# ifdef CORY
X	if (ucount() > MAXUSERS)  {
X		writel (user1a);
X		wrint (MAXUSERS);
X		writel (user1b);
X		getout();
X	}
X# endif
X
X							/* get terminal
X							 * capabilities, and
X					   		 * decide if it can
X							 * cursor address */
X	tflag = getcaps (getenv ("TERM"));
X							/* use whole screen
X							 * for text */
X	if (tflag)
X		begscr = 0;
X	t = time(0);
X	srandom(t);					/* 'random' seed */
X
X#ifdef V7
X	while (*++argv != 0)				/* process arguments */
X#else
X	while (*++argv != -1)				/* process arguments */
X#endif
X		getarg (&argv);
X	args[acnt] = '\0';
X	if (tflag)  {					/* clear screen */
X		noech &= ~(CRMOD|XTABS);
X		raw &= ~(CRMOD|XTABS);
X		clear();
X	}
X	fixtty (raw);					/* go into raw mode */
X
X							/* check if restored
X							 * game and save flag
X							 * for later */
X	if (rfl = rflag)  {
X		text (message);				/* print message */
X		text (contin);
X		wrboard();				/* print board */
X							/* if new game, pretend
X							 * to be a non-restored
X							 * game */
X		if (cturn == 0)
X			rflag = 0;
X	} else  {
X		rscore = wscore = 0;			/* zero score */
X		text (message);				/* update message
X							 * without pausing */
X
X		if (aflag)  {				/* print rules */
X			writel (rules);
X			if (yorn(0))  {
X
X				fixtty (old);		/* restore tty */
X				execl (TEACH,"teachgammon",args,0);
X
X				tflag = 0;		/* error! */
X				writel (noteach);
X				exit();
X			} else  {			/* if not rules, then
X							 * instructions */
X				writel (need);
X				if (yorn(0))  {		/* print instructions */
X					clear();
X					text (instr);
X				}
X			}
X		}
X
X		init();					/* initialize board */
X
X		if (pnum == 2)  {			/* ask for color(s) */
X			writec ('\n');
X			writel (askcol);
X			while (pnum == 2)  {
X				c = readc();
X				switch (c)  {
X
X				case 'R':		/* red */
X					pnum = -1;
X					break;
X
X				case 'W':		/* white */
X					pnum = 1;
X					break;
X
X				case 'B':		/* both */
X					pnum = 0;
X					break;
X
X				case 'P':
X					if (iroll)
X						break;
X					if (tflag)
X						curmove (curr,0);
X					else
X						writec ('\n');
X					writel ("Password:");
X					signal (14,getout);
X					cflag = 1;
X					alarm (10);
X					for (i = 0; i < 10; i++)  {
X						pbuf[i] = readc();
X						if (pbuf[i] == '\n')
X							break;
X					}
X					if (i == 10)
X						while (readc() != '\n');
X					alarm (0);
X					cflag = 0;
X					if (i < 10)
X						pbuf[i] = '\0';
X					for (i = 0; i < 9; i++)
X						if (pbuf[i] != password[i])
X							getout();
X					iroll = 1;
X					if (tflag)
X						curmove (curr,0);
X					else
X						writec ('\n');
X					writel (askcol);
X					break;
X
X				default:		/* error */
X					writec ('\007');
X				}
X			}
X		} else  if (!aflag)
X							/* pause to read
X							 * message */
X			text (contin);
X
X		wrboard();				/* print board */
X
X		if (tflag)
X			curmove (18,0);
X		else
X			writec ('\n');
X	}
X							/* limit text to bottom
X							 * of screen */
X	if (tflag)
X		begscr = 17;
X
X	for (;;)  {					/* begin game! */
X							/* initial roll if
X							 * needed */
X		if ((! rflag) || raflag)
X			roll();
X
X							/* perform ritual of
X							 * first roll */
X		if (! rflag)  {
X			if (tflag)
X				curmove (17,0);
X			while (D0 == D1)		/* no doubles */
X				roll();
X
X							/* print rolls */
X			writel (rollr);
X			writec (D0+'0');
X			writel (rollw);
X			writec (D1+'0');
X
X							/* winner goes first */
X			if (D0 > D1)  {
X				writel (rstart);
X				cturn = 1;
X			} else  {
X				writel (wstart);
X				cturn = -1;
X			}
X		}
X
X							/* initalize variables
X							 * according to whose
X							 * turn it is */
X
X		if (cturn == 1)  {			    /* red */
X			home = 25;
X			bar = 0;
X			inptr = &in[1];
X			inopp = &in[0];
X			offptr = &off[1];
X			offopp = &off[0];
X			Colorptr = &color[1];
X			colorptr = &color[3];
X			colen = 3;
X		} else  {				    /* white */
X			home = 0;
X			bar = 25;
X			inptr = &in[0];
X			inopp = &in[1];
X			offptr = &off[0];
X			offopp = &off[1];
X			Colorptr = &color[0];
X			colorptr = &color[2];
X			colen = 5;
X		}
X
X							/* do first move
X							 * (special case) */
X		if (! (rflag && raflag))  {
X			if (cturn == pnum)		/* computer's move */
X				move (0);
X			else  {				/* player's move */
X				mvlim = movallow();
X							/* reprint roll */
X				if (tflag)
X					curmove (cturn == -1? 18: 19,0);
X				proll();
X				getmove();		/* get player's move */
X			}
X		}
X		if (tflag)  {
X			curmove (17,0);
X			cline();
X			begscr = 18;
X		}
X
X							/* no longer any diff-
X							 * erence between normal
X							 * game and recovered
X							 * game. */
X		rflag = 0;
X
X							/* move as long as it's
X							 * someone's turn */
X		while (cturn == 1 || cturn == -1)  {
X
X							/* board maintainence */
X			if (tflag)
X				refresh();		/* fix board */
X			else
X							/* redo board if -p */
X				if (cturn == bflag || bflag == 0)
X					wrboard();
X
X							/* do computer's move */
X			if (cturn == pnum)  {
X				move (1);
X
X							/* see if double
X							 * refused */
X				if (cturn == -2 || cturn == 2)
X					break;
X
X							/* check for winning
X							 * move */
X				if (*offopp == 15)  {
X					cturn *= -2;
X					break;
X				}
X				continue;
X
X			}
X
X							/* (player's move) */
X
X							/* clean screen if
X							 * safe */
X			if (tflag && hflag)  {
X				curmove (20,0);
X				clend ();
X				hflag = 1;
X			}
X
X							/* if allowed, give him
X							 * a chance to double */
X			if (dlast != cturn && gvalue < 64)  {
X				if (tflag)
X					curmove (cturn == -1? 18: 19,0);
X				writel (*Colorptr);
X				c = readc();
X
X							/* character cases */
X				switch (c)  {
X
X							/* reprint board */
X				case 'R':
X					wrboard();
X					break;
X
X							/* save game */
X				case 'S':
X					raflag = 1;
X					save (1);
X					break;
X
X							/* quit */
X				case 'Q':
X					quit();
X					break;
X
X							/* double */
X				case 'D':
X					dble();
X					break;
X
X							/* roll */
X				case ' ':
X				case '\n':
X					roll();
X					writel (" rolls ");
X					writec (D0+'0');
X					writec (' ');
X					writec (D1+'0');
X					writel (".  ");
X
X							/* see if he can move */
X					if ( (mvlim = movallow()) == 0)  {
X
X							/* can't move */
X						writel (toobad1);
X						writel (*colorptr);
X						writel (unable);
X						if (tflag)  {
X							if (pnum)  {
X								buflush();
X								sleep (MVPAUSE);
X							}
X						}
X						nexturn();
X						break;
X					}
X
X							/* get move */
X					getmove();
X
X							/* okay to clean
X							 * screen */
X					hflag = 1;
X					break;
X
X							/* invalid character */
X				default:
X
X							/* print help message */
X					if (tflag)
X						curmove (20,0);
X					else
X						writec ('\n');
X					text (helpm);
X					if (tflag)
X						curmove (cturn == -1? 18: 19,0);
X					else
X						writec ('\n');
X
X							/* don't erase */
X					hflag = 0;
X				}
X			} else  {			/* couldn't double */
X
X							/* print roll */
X				roll();
X				if (tflag)
X					curmove (cturn == -1? 18: 19,0);
X				proll ();
X
X							/* can he move? */
X				if ((mvlim = movallow()) == 0)  {
X
X							/* he can't */
X					writel (toobad2);
X					writel (*colorptr);
X					writel (cantmv);
X					buflush();
X					sleep (MVPAUSE);
X					nexturn();
X					continue;
X				}
X
X							/* get move */
X				getmove();
X			}
X		}
X
X							/* don't worry about who
X							 * won if quit */
X		if (cturn == 0)
X			break;
X
X							/* fix cturn = winner */
X		cturn /= -2;
X
X							/* final board pos. */
X		if (tflag)
X			refresh();
X
X							/* backgammon? */
X		mflag = 0;
X		l = bar+7*cturn;
X		for (i = bar; i != l; i += cturn)
X			if (board[i]*cturn)  mflag++;
X
X							/* compute game value */
X		if (tflag)
X			curmove (20,0);
X		if (*offopp == 15)  {
X			if (mflag)  {
X				writel (bgammon);
X				gvalue *= 3;
X			}
X			else  if (*offptr <= 0)  {
X				writel (gammon);
X				gvalue *= 2;
X			}
X		}
X
X							/* report situation */
X		if (cturn == -1)  {
X			writel ("Red wins ");
X			rscore += gvalue;
X		} else {
X			writel ("White wins ");
X			wscore += gvalue;
X		}
X		wrint (gvalue);
X		writel (" point");
X		if (gvalue > 1)
X			writec ('s');
X		writel (".\n");
X
X							/* write score */
X		wrscore();
X
X							/* check user count */
X# ifdef CORY
X		if (ucount() > MAXUSERS)  {
X			writel (user2a);
X			wrint (MAXUSERS);
X			writel (user2b);
X			rfl = 1;
X			break;
X		}
X# endif
X
X							/* see if he wants
X							 * another game */
X		writel (again);
X		if ((i = yorn ('S')) == 0)
X			break;
X
X		init();
X		if (i == 2)  {
X			writel ("  Save.\n");
X			cturn = 0;
X			save (0);
X		}
X
X							/* yes, reset game */
X		wrboard();
X	}
X
X	/* give him a chance to save if game was recovered */
X	if (rfl && cturn)  {
X		writel (svpromt);
X		if (yorn (0))  {
X							/* re-initialize for
X							 * recovery */
X			init();
X			cturn = 0;
X			save(0);
X		}
X	}
X
X							/* leave peacefully */
X	getout ();
X}
END_OF_main.c
if test 11532 -ne `wc -c <main.c`; then
    echo shar: \"main.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f move.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"move.c\"
else
echo shar: Extracting \"move.c\" \(11131 characters\)
sed "s/^X//" >move.c <<'END_OF_move.c'
X/*
X * Copyright (c) 1980 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)move.c	5.3 (Berkeley) 2/16/88";
X#endif /* not lint */
X
X#include "back.h"
X
X#ifdef DEBUG
X#include <stdio.h>
XFILE	*trace;
Xstatic char	tests[20];
X#endif
X
Xstruct BOARD  {				/* structure of game position */
X	int	b_board[26];			/* board position */
X	int	b_in[2];			/* men in */
X	int	b_off[2];			/* men off */
X	int	b_st[4], b_fn[4];		/* moves */
X
X	struct BOARD	*b_next;		/* forward queue pointer */
X};
X
Xstruct BOARD *freeq = 0;
Xstruct BOARD *checkq = 0;
Xstruct BOARD *bsave();
Xstruct BOARD *nextfree();
X
X					/* these variables are values for the
X					 * candidate move */
Xstatic int	ch;				/* chance of being hit */
Xstatic int	op;				/* computer's open men */
Xstatic int	pt;				/* comp's protected points */
Xstatic int	em;				/* farthest man back */
Xstatic int	frc;				/* chance to free comp's men */
Xstatic int	frp;				/* chance to free pl's men */
X
X					/* these values are the values for the
X					 * move chosen (so far) */
Xstatic int	chance;				/* chance of being hit */
Xstatic int	openmen;			/* computer's open men */
Xstatic int	points;				/* comp's protected points */
Xstatic int	endman;				/* farthest man back */
Xstatic int	barmen;				/* men on bar */
Xstatic int	menin;				/* men in inner table */
Xstatic int	menoff;				/* men off board */
Xstatic int	oldfrc;				/* chance to free comp's men */
Xstatic int	oldfrp;				/* chance to free pl's men */
X
Xstatic int	cp[5];				/* candidate start position */
Xstatic int	cg[5];				/* candidate finish position */
X
Xstatic int	race;				/* game reduced to a race */
X
Xmove (okay)
Xint	okay;					/* zero if first move */
X{
X	register int	i;		/* index */
X	register int	l;		/* last man */
X
X	if (okay)  {
X						/* see if comp should double */
X		if (gvalue < 64 && dlast != cturn && dblgood())  {
X			writel (*Colorptr);
X			dble();			    /* double */
X						    /* return if declined */
X			if (cturn != 1 && cturn != -1)
X				return;
X		}
X		roll();
X	}
X
X	race = 0;
X	for (i = 0; i < 26; i++)  {
X		if (board[i] < 0)
X			l = i;
X	}
X	for (i = 0; i < l; i++)  {
X		if (board[i] > 0)
X			break;
X	}
X	if (i == l)
X		race = 1;
X
X						/* print roll */
X	if (tflag)
X		curmove (cturn == -1? 18: 19,0);
X	writel (*Colorptr);
X	writel (" rolls ");
X	writec (D0+'0');
X	writec (' ');
X	writec (D1+'0');
X						/* make tty interruptable
X						 * while thinking */
X	if (tflag)
X		cline();
X	fixtty (noech);
X
X						/* find out how many moves */
X	mvlim = movallow();
X	if (mvlim == 0)  {
X		writel (" but cannot use it.\n");
X		nexturn();
X		fixtty (raw);
X		return;
X	}
X
X						/* initialize */
X	for (i = 0; i < 4; i++)
X		cp[i] = cg[i] = 0;
X
X						/* strategize */
X	trymove (0,0);
X	pickmove();
X
X						/* print move */
X	writel (" and moves ");
X	for (i = 0; i < mvlim; i++)  {
X		if (i > 0)
X			writec (',');
X		wrint (p[i] = cp[i]);
X		writec ('-');
X		wrint (g[i] = cg[i]);
X		makmove (i);
X	}
X	writec ('.');
X
X						/* print blots hit */
X	if (tflag)
X		curmove (20,0);
X	else
X		writec ('\n');
X	for (i = 0; i < mvlim; i++)
X		if (h[i])
X			wrhit(g[i]);
X						/* get ready for next move */
X	nexturn();
X	if (!okay)  {
X		buflush();
X		sleep (3);
X	}
X	fixtty (raw);				/* no more tty interrupt */
X}
X
Xtrymove (mvnum,swapped)
Xregister int	mvnum;				/* number of move (rel zero) */
Xint		swapped;			/* see if swapped also tested */
X
X{
X	register int	pos;			/* position on board */
X	register int	rval;			/* value of roll */
X
X						/* if recursed through all dice
X						 * values, compare move */
X	if (mvnum == mvlim)  {
X		binsert (bsave());
X		return;
X	}
X
X						/* make sure dice in always
X						 * same order */
X	if (d0 == swapped)
X		swap;
X						/* choose value for this move */
X	rval = dice[mvnum != 0];
X
X						/* find all legitimate moves */
X	for (pos = bar; pos != home; pos += cturn)  {
X						/* fix order of dice */
X		if (d0 == swapped)
X			swap;
X						/* break if stuck on bar */
X		if (board[bar] != 0 && pos != bar)
X			break;
X						/* on to next if not occupied */
X		if (board[pos]*cturn <= 0)
X			continue;
X						/* set up arrays for move */
X		p[mvnum] = pos;
X		g[mvnum] = pos+rval*cturn;
X		if (g[mvnum]*cturn >= home)  {
X			if (*offptr < 0)
X				break;
X			g[mvnum] = home;
X		}
X						/* try to move */
X		if (makmove (mvnum))
X			continue;
X		else
X			trymove (mvnum+1,2);
X						/* undo move to try another */
X		backone (mvnum);
X	}
X
X						/* swap dice and try again */
X	if ((!swapped) && D0 != D1)
X		trymove (0,1);
X}
X
Xstruct BOARD *
Xbsave ()  {
X	register int	i;		/* index */
X	struct BOARD	*now;		/* current position */
X
X	now = nextfree ();		/* get free BOARD */
X
X					/* store position */
X	for (i = 0; i < 26; i++)
X		now->b_board[i] = board[i];
X	now->b_in[0] = in[0];
X	now->b_in[1] = in[1];
X	now->b_off[0] = off[0];
X	now->b_off[1] = off[1];
X	for (i = 0; i < mvlim; i++)  {
X		now->b_st[i] = p[i];
X		now->b_fn[i] = g[i];
X	}
X	return (now);
X}
X
Xbinsert (new)
Xstruct BOARD	*new;					/* item to insert */
X{
X	register struct BOARD	*p = checkq;		/* queue pointer */
X	register int		result;			/* comparison result */
X
X	if (p == 0)  {				/* check if queue empty */
X		checkq = p = new;
X		p->b_next = 0;
X		return;
X	}
X
X	result = bcomp (new,p);			/* compare to first element */
X	if (result < 0)  {				/* insert in front */
X		new->b_next = p;
X		checkq = new;
X		return;
X	}
X	if (result == 0)  {				/* duplicate entry */
X		mvcheck (p,new);
X		makefree (new);
X		return;
X	}
X
X	while (p->b_next != 0)  {		/* traverse queue */
X		result = bcomp (new,p->b_next);
X		if (result < 0)  {			/* found place */
X			new->b_next = p->b_next;
X			p->b_next = new;
X			return;
X		}
X		if (result == 0)  {			/* duplicate entry */
X			mvcheck (p->b_next,new);
X			makefree (new);
X			return;
X		}
X		p = p->b_next;
X	}
X						/* place at end of queue */
X	p->b_next = new;
X	new->b_next = 0;
X}
X
Xbcomp (a,b)
Xstruct BOARD	*a;
Xstruct BOARD	*b;
X{
X	register int	*aloc = a->b_board;	/* pointer to board a */
X	register int	*bloc = b->b_board;	/* pointer to board b */
X	register int	i;			/* index */
X	int		result;			/* comparison result */
X
X	for (i = 0; i < 26; i++)  {		/* compare boards */
X		result = cturn*(aloc[i]-bloc[i]);
X		if (result)
X			return (result);		/* found inequality */
X	}
X	return (0);				/* same position */
X}
X
Xmvcheck (incumbent,candidate)
Xregister struct BOARD 	*incumbent;
Xregister struct BOARD 	*candidate;
X{
X	register int	i;
X	register int	result;
X
X	for (i = 0; i < mvlim; i++)  {
X		result = cturn*(candidate->b_st[i]-incumbent->b_st[i]);
X		if (result > 0)
X			return;
X		if (result < 0)
X			break;
X	}
X	if (i == mvlim)
X		return;
X	for (i = 0; i < mvlim; i++)  {
X		incumbent->b_st[i] = candidate->b_st[i];
X		incumbent->b_fn[i] = candidate->b_fn[i];
X	}
X}
X
Xmakefree (dead)
Xstruct BOARD	*dead;			/* dead position */
X{
X	dead->b_next = freeq;			/* add to freeq */
X	freeq = dead;
X}
X
Xstruct BOARD *
Xnextfree ()  {
X	struct BOARD	*new;
X
X	if (freeq == 0)  {
X		new = (struct BOARD *)calloc (1,sizeof (struct BOARD));
X		if (new == 0)  {
X			writel ("\nOut of memory\n");
X			getout();
X		}
X		new->b_next = 0;
X		return (new);
X	}
X
X	new = freeq;
X	freeq = freeq->b_next;
X	return new;
X}
X
Xpickmove ()  {
X						/* current game position */
X	register struct BOARD	*now = bsave();
X	register struct BOARD	*next;		/* next move */
X
X#ifdef DEBUG
X	if (trace == NULL)
X		trace = fopen ("bgtrace","w");
X	fprintf (trace,"\nRoll:  %d %d%s\n",D0,D1,race? " (race)": "");
X	fflush (trace);
X#endif
X	do  {				/* compare moves */
X		bcopy (checkq);
X		next = checkq->b_next;
X		makefree (checkq);
X		checkq = next;
X		movcmp();
X	} while (checkq != 0);
X
X	bcopy (now);
X}
X
Xbcopy (s)
Xregister struct BOARD	*s;			/* game situation */
X{
X	register int	i;			/* index */
X
X	for (i = 0; i < 26; i++)
X		board[i] = s->b_board[i];
X	for (i = 0; i < 2; i++)  {
X		in[i] = s->b_in[i];
X		off[i] = s->b_off[i];
X	}
X	for (i = 0; i < mvlim; i++)  {
X		p[i] = s->b_st[i];
X		g[i] = s->b_fn[i];
X	}
X}
X
Xmovcmp ()  {
X	register int	i;
X	register int	c;
X
X#ifdef DEBUG
X	if (trace == NULL)
X		trace = fopen ("bgtrace","w");
X#endif
X
X	odds (0,0,0);
X	if (!race)  {
X		ch = op = pt = 0;
X		for (i = 1; i < 25; i++)  {
X			if (board[i] == cturn)
X				ch = canhit (i,1);
X				op += abs (bar-i);
X		}
X		for (i = bar+cturn; i != home; i += cturn)
X			if (board[i]*cturn > 1)
X				pt += abs(bar-i);
X		frc = freemen (bar)+trapped (bar,cturn);
X		frp = freemen (home)+trapped (home,-cturn);
X	}
X	for (em = bar; em != home; em += cturn)
X		if (board[em]*cturn > 0)
X			break;
X	em = abs(home-em);
X#ifdef DEBUG
X	fputs ("Board: ",trace);
X	for (i = 0; i < 26; i++)
X		fprintf (trace, " %d",board[i]);
X	if (race)
X		fprintf (trace,"\n\tem = %d\n",em);
X	else
X		fprintf (trace,
X			"\n\tch = %d, pt = %d, em = %d, frc = %d, frp = %d\n",
X			ch,pt,em,frc,frp);
X	fputs ("\tMove: ",trace);
X	for (i = 0; i < mvlim; i++)
X		fprintf (trace," %d-%d",p[i],g[i]);
X	fputs ("\n",trace);
X	fflush (trace);
X	strcpy (tests,"");
X#endif
X	if ((cp[0] == 0 && cg[0] == 0) || movegood())  {
X#ifdef DEBUG
X		fprintf (trace,"\t[%s] ... wins.\n",tests);
X		fflush (trace);
X#endif
X		for (i = 0; i < mvlim; i++)  {
X			cp[i] = p[i];
X			cg[i] = g[i];
X		}
X		if (!race)  {
X			chance = ch;
X			openmen = op;
X			points = pt;
X			endman = em;
X			barmen = abs(board[home]);
X			oldfrc = frc;
X			oldfrp = frp;
X		}
X		menin = *inptr;
X		menoff = *offptr;
X	}
X#ifdef DEBUG
X	else  {
X		fprintf (trace,"\t[%s] ... loses.\n",tests);
X		fflush (trace);
X	}
X#endif
X}
X
Xmovegood ()  {
X	register int	n;
X
X	if (*offptr == 15)
X		return (1);
X	if (menoff == 15)
X		return (0);
X	if (race)  {
X#ifdef DEBUG
X		strcat (tests,"o");
X#endif
X		if (*offptr-menoff)
X			return (*offptr > menoff);
X#ifdef DEBUG
X		strcat (tests,"e");
X#endif
X		if (endman-em)
X			return (endman > em);
X#ifdef DEBUG
X		strcat (tests,"i");
X#endif
X		if (menin == 15)
X			return (0);
X		if (*inptr == 15)
X			return (1);
X#ifdef DEBUG
X		strcat (tests,"i");
X#endif
X		if (*inptr-menin)
X			return (*inptr > menin);
X		return (rnum(2));
X	} else  {
X		n = barmen-abs(board[home]);
X#ifdef DEBUG
X		strcat (tests,"c");
X#endif
X		if (abs(chance-ch)+25*n > rnum(150))
X			return (n? (n < 0): (ch < chance));
X#ifdef DEBUG
X		strcat (tests,"o");
X#endif
X		if (*offptr-menoff)
X			return (*offptr > menoff);
X#ifdef DEBUG
X		strcat (tests,"o");
X#endif
X		if (abs(openmen-op) > 7+rnum(12))
X			return (openmen > op);
X#ifdef DEBUG
X		strcat (tests,"b");
X#endif
X		if (n)
X			return (n < 0);
X#ifdef DEBUG
X		strcat (tests,"e");
X#endif
X		if (abs(endman-em) > rnum(2))
X			return (endman > em);
X#ifdef DEBUG
X		strcat (tests,"f");
X#endif
X		if (abs(frc-oldfrc) > rnum(2))
X			return (frc < oldfrc);
X#ifdef DEBUG
X		strcat (tests,"p");
X#endif
X		if (abs(n = pt-points) > rnum(4))
X			return (n > 0);
X#ifdef DEBUG
X		strcat (tests,"i");
X#endif
X		if (*inptr-menin)
X			return (*inptr > menin);
X#ifdef DEBUG
X		strcat (tests,"f");
X#endif
X		if (abs(frp-oldfrp) > rnum(2))
X			return (frp > oldfrp);
X		return (rnum(2));
X	}
X}
END_OF_move.c
if test 11131 -ne `wc -c <move.c`; then
    echo shar: \"move.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f save.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"save.c\"
else
echo shar: Extracting \"save.c\" \(3405 characters\)
sed "s/^X//" >save.c <<'END_OF_save.c'
X/*
X * Copyright (c) 1980 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)save.c	5.2 (Berkeley) 2/16/88";
X#endif /* not lint */
X
X#include "back.h"
X
Xextern int	errno;
X
Xstatic char	confirm[] = "Are you sure you want to leave now?";
Xstatic char	prompt[] = "Enter a file name:  ";
Xstatic char	exist1[] = "The file '";
Xstatic char	exist2[] =
X	"' already exists.\nAre you sure you want to use this file?";
Xstatic char	cantuse[] = "\nCan't use ";
Xstatic char	saved[] = "This game has been saved on the file '";
Xstatic char	type[] = "'.\nType \"backgammon ";
Xstatic char	rec[] = "\" to recover your game.\n\n";
Xstatic char	cantrec[] = "Can't recover file:  ";
X
Xsave (n)
Xregister int	n;
X
X{
X	register int	fdesc;
X	register char	*fs;
X	char		fname[50];
X
X	if (n)  {
X		if (tflag)  {
X			curmove (20,0);
X			clend();
X		} else
X			writec ('\n');
X		writel (confirm);
X		if (! yorn(0))
X			return;
X	}
X	cflag = 1;
X	for (;;)  {
X		writel (prompt);
X		fs = fname;
X		while ((*fs = readc()) != '\n')  {
X			if (*fs == tty.sg_erase)  {
X				if (fs > fname)  {
X					fs--;
X					if (tflag)
X						curmove (curr,curc-1);
X					else
X						writec (*fs);
X				} else
X					writec ('\007');
X				continue;
X			}
X			writec (*fs++);
X		}
X		*fs = '\0';
X		if ((fdesc = open(fname,2)) == -1 && errno == 2)  {
X			if ((fdesc = creat (fname,0700)) != -1)
X			break;
X		}
X		if (fdesc != -1)  {
X			if (tflag)  {
X				curmove (18,0);
X				clend();
X			} else
X				writec ('\n');
X			writel (exist1);
X			writel (fname);
X			writel (exist2);
X			cflag = 0;
X			close (fdesc);
X			if (yorn (0))  {
X				unlink (fname);
X				fdesc = creat (fname,0700);
X				break;
X			} else  {
X				cflag = 1;
X				continue;
X			}
X		}
X		writel (cantuse);
X		writel (fname);
X		writel (".\n");
X		close (fdesc);
X		cflag = 1;
X	}
X	write (fdesc,board,sizeof board);
X	write (fdesc,off,sizeof off);
X	write (fdesc,in,sizeof in);
X	write (fdesc,dice,sizeof dice);
X	write (fdesc,&cturn,sizeof cturn);
X	write (fdesc,&dlast,sizeof dlast);
X	write (fdesc,&pnum,sizeof pnum);
X	write (fdesc,&rscore,sizeof rscore);
X	write (fdesc,&wscore,sizeof wscore);
X	write (fdesc,&gvalue,sizeof gvalue);
X	write (fdesc,&raflag,sizeof raflag);
X	close (fdesc);
X	if (tflag)
X		curmove (18,0);
X	writel (saved);
X	writel (fname);
X	writel (type);
X	writel (fname);
X	writel (rec);
X	if (tflag)
X		clend();
X	getout ();
X}
X
Xrecover (s)
Xchar	*s;
X
X{
X	register int	i;
X	int		fdesc;
X
X	if ((fdesc = open (s,0)) == -1)
X		norec (s);
X	read (fdesc,board,sizeof board);
X	read (fdesc,off,sizeof off);
X	read (fdesc,in,sizeof in);
X	read (fdesc,dice,sizeof dice);
X	read (fdesc,&cturn,sizeof cturn);
X	read (fdesc,&dlast,sizeof dlast);
X	read (fdesc,&pnum,sizeof pnum);
X	read (fdesc,&rscore,sizeof rscore);
X	read (fdesc,&wscore,sizeof wscore);
X	read (fdesc,&gvalue,sizeof gvalue);
X	read (fdesc,&raflag,sizeof raflag);
X	close (fdesc);
X	rflag = 1;
X}
X
Xnorec (s)
Xregister char	*s;
X
X{
X	register char	*c;
X
X	tflag = 0;
X	writel (cantrec);
X	c = s;
X	while (*c != '\0')
X		writec (*c++);
X	getout ();
X}
END_OF_save.c
if test 3405 -ne `wc -c <save.c`; then
    echo shar: \"save.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0