Path: uunet!husc6!bloom-beacon!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games-request
From: games-request@tekred.TEK.COM
Newsgroups: comp.sources.games
Subject: v03i094: backgammon - 4.3BSD backgammon game, Part01/03
Message-ID: <2265@tekred.TEK.COM>
Date: 9 Mar 88 17:43:34 GMT
Sender: billr@tekred.TEK.COM
Lines: 2428
Approved: billr@tekred.TEK.COM
Submitted by: John Gilmore
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 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 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 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 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 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
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 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
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 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