BSD 4_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 8 Jun 1982 12:34:50 +0000 (04:34 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 8 Jun 1982 12:34:50 +0000 (04:34 -0800)
Work on file usr/src/games/backgammon/allow.c
Work on file usr/src/games/backgammon/board.c
Work on file usr/src/games/backgammon/check.c
Work on file usr/src/games/backgammon/extra.c
Work on file usr/src/games/backgammon/init.c
Work on file usr/src/games/backgammon/move.c
Work on file usr/src/games/backgammon/odds.c
Work on file usr/src/games/backgammon/one.c
Work on file usr/src/games/backgammon/data.c
Work on file usr/src/games/backgammon/table.c
Work on file usr/src/games/backgammon/text.c
Work on file usr/src/games/backgammon/teach.c
Work on file usr/src/games/backgammon/ttext1.c
Work on file usr/src/games/backgammon/tutor.c
Work on file usr/src/games/backgammon/tutor.h
Work on file usr/src/games/backgammon/backgammon.src

Synthesized-from: CSRG/cd1/4.2

16 files changed:
usr/src/games/backgammon/allow.c [new file with mode: 0644]
usr/src/games/backgammon/backgammon.src [new file with mode: 0644]
usr/src/games/backgammon/board.c [new file with mode: 0644]
usr/src/games/backgammon/check.c [new file with mode: 0644]
usr/src/games/backgammon/data.c [new file with mode: 0644]
usr/src/games/backgammon/extra.c [new file with mode: 0644]
usr/src/games/backgammon/init.c [new file with mode: 0644]
usr/src/games/backgammon/move.c [new file with mode: 0644]
usr/src/games/backgammon/odds.c [new file with mode: 0644]
usr/src/games/backgammon/one.c [new file with mode: 0644]
usr/src/games/backgammon/table.c [new file with mode: 0644]
usr/src/games/backgammon/teach.c [new file with mode: 0644]
usr/src/games/backgammon/text.c [new file with mode: 0644]
usr/src/games/backgammon/ttext1.c [new file with mode: 0644]
usr/src/games/backgammon/tutor.c [new file with mode: 0644]
usr/src/games/backgammon/tutor.h [new file with mode: 0644]

diff --git a/usr/src/games/backgammon/allow.c b/usr/src/games/backgammon/allow.c
new file mode 100644 (file)
index 0000000..fa57c3e
--- /dev/null
@@ -0,0 +1,74 @@
+static char sccsid[] = "       allow.c 4.1     82/05/11        ";
+
+#include "back.h"
+
+movallow ()  {
+
+       register int    i, m, iold;
+       int             r;
+
+       if (d0)
+               swap;
+       m = (D0 == D1? 4: 2);
+       for (i = 0; i < 4; i++)
+               p[i] = bar;
+       i = iold = 0;
+       while (i < m)  {
+               if (*offptr == 15)
+                       break;
+               h[i] = 0;
+               if (board[bar])  {
+                       if (i == 1 || m == 4)
+                               g[i] = bar+cturn*D1;
+                       else
+                               g[i] = bar+cturn*D0;
+                       if (r = makmove(i))  {
+                               if (d0 || m == 4)
+                                       break;
+                               swap;
+                               movback (i);
+                               if (i > iold)
+                                       iold = i;
+                               for (i = 0; i < 4; i++)
+                                       p[i] = bar;
+                               i = 0;
+                       } else
+                               i++;
+                       continue;
+               }
+               if ((p[i] += cturn) == home)  {
+                       if (i > iold)
+                               iold = i;
+                       if (m == 2 && i)  {
+                               movback(i);
+                               p[i--] = bar;
+                               if (p[i] != bar)
+                                       continue;
+                               else
+                                       break;
+                       }
+                       if (d0 || m == 4)
+                               break;
+                       swap;
+                       movback (i);
+                       for (i = 0; i < 4; i++)
+                               p[i] = bar;
+                       i = 0;
+                       continue;
+               }
+               if (i == 1 || m == 4)
+                       g[i] = p[i]+cturn*D1;
+               else
+                       g[i] = p[i]+cturn*D0;
+               if (g[i]*cturn > home)  {
+                       if (*offptr >= 0)
+                               g[i] = home;
+                       else
+                               continue;
+               }
+               if (board[p[i]]*cturn > 0 && (r = makmove(i)) == 0)
+                       i++;
+       }
+       movback (i);
+       return (iold > i? iold: i);
+}
diff --git a/usr/src/games/backgammon/backgammon.src b/usr/src/games/backgammon/backgammon.src
new file mode 100644 (file)
index 0000000..6186473
--- /dev/null
@@ -0,0 +1,190 @@
+.\"    backgammon.src  4.1     82/05/11
+.th BACKGAMMON PUBLIC \n(mo/\n(dy/\n(yr
+.sh NAME
+backgammon - the game of backgammon
+.sh SYNOPSIS
+.bd backgammon
+[ - ] [ n r w b pr pw pb t\c
+.it term
+s\c
+.it file
+]
+.sh DESCRIPTION
+This program lets you play backgammon against the computer
+or against a "friend".
+All commands only are one letter,
+so you don't need to type a carriage return,
+except at the end of a move.
+The program is mostly self documenting,
+so that a question mark (?) will usually get some help.
+If you answer `y' when the program asks if you want the rules,
+you will get text explaining the rules of the game,
+some hints on strategy,
+instruction on how to use the program,
+and a tutorial consisting of a practice game against the computer.
+A description of how to use the program can be
+obtained by answering `y' when it asks if you want instructions.
+.s3
+The possible arguments for backgammon
+(most are unnecesary but some are very convenient)
+consist of:
+.ne 11
+.s3
+.na
+.lp 16 8
+.bn n
+don't ask for rules or instructions
+.lp 16 8
+.bn r
+player is red (implies n)
+.lp 16 8
+.bn w
+player is white (implies n)
+.lp 16 8
+.bn b
+two players, red and white (implies n)
+.lp 16 8
+.bn pr
+print the board before red's turn
+.lp 16 8
+.bn pw
+print the board before white's turn
+.lp 16 8
+.bn pb
+print the board before both player's turn
+.lp 16 8
+.bn t\fiterm
+terminal is type
+.it term,
+uses /etc/termcap
+.lp 16 8
+.bn s\fifile
+recover previously saved game from
+.it file.
+(This can also be done by executing the saved file,
+i.e., typing its name in as a command)
+.s3
+.ad
+.i0
+Arguments may be optionally preceded by a `-'.
+Several arguments may be concatenated together,
+but not after `s' or `t' arguments,
+since they can be followed by an arbitrary string.
+Any unrecognized arguments are ignored.
+An argument of a lone `-' gets a description of possible arguments.
+.s3
+If
+.it term
+has capabilities for direct cursor movement (see ttycap(VII)),
+.it backgammon
+"fixes" the board after each move,
+so the board does not need to be reprinted,
+unless the screen suffers some horrendous malady.
+Also, any `p' option will be ignored.
+(The `t' option is not necessary unless the terminal type does not match
+the entry in the /etc/htmp data base.)
+.sh QUICK\ REFERENCE
+When the program prompts by typing only your color,
+type a space or carriage return to roll, or
+.ne 5
+.s3
+.na
+.lp 16 8
+.bn d
+to double
+.lp 16 8
+.bn p
+to print the board
+.lp 16 8
+.bn q
+to quit
+.lp 16 8
+.bn s
+to save the game for later
+.s3
+.i0
+.ad
+When the program prompts with 'Move:', type
+.ne 4
+.s3
+.na
+.lp 16 8
+.bn p
+to print the board
+.lp 16 8
+.bn q
+to quit
+.lp 16 8
+.bn s
+to save the game
+.ad
+.i0
+.s3
+or a
+.it move,
+which is a sequence of
+.ne 4
+.s3
+.na
+.lp 16 8
+.bn s-f
+move from
+.bd s
+to
+.bd f
+.lp 16 8
+.bn s/r
+move one man on
+.bd s
+the roll
+.bd r
+.ad
+.i0
+.s3
+separated by commas or spaces and ending with a newline.
+Available abbreviations are
+.ne 4
+.s3
+.na
+.lp 18 10
+.bn s-f1-f2
+means
+.bd s-f1,f1-f2
+.lp 18 10
+.bn s/r1r2
+means
+.bd s/r1,s/r2
+.ad
+.i0
+.s3
+Use `b' for bar and `h' for home,
+or 0 or 25 as appropriate.
+.sh AUTHOR
+Alan Char
+.sh FILES
+.lp 30 25
+.bn /mnt/alan/:toys/teachgammon
+- rules and tutorial
+.br
+.lp 30 25
+.bn /etc/htmp
+- data base on user's environment
+.br
+.lp 30 25
+.bn /etc/termcap
+- terminal capabilities
+.i0
+.sh BUGS
+The program's strategy needs much work.
+.s3
+/mnt/alan/:toys/teachgammon was removed to preserve space in /usr/public
+.sh COMMENTS
+The program is still under development,
+so a description of any bugs found should be mailed to
+.bd alan.
+.s3
+Because of the dynamic state of the program
+(constantly changing),
+the file
+.it /mnt/alan/:toys/gammon.news
+lists current modifications to the program.
diff --git a/usr/src/games/backgammon/board.c b/usr/src/games/backgammon/board.c
new file mode 100644 (file)
index 0000000..2565328
--- /dev/null
@@ -0,0 +1,141 @@
+static char sccsid[] = "       board.c 4.1     82/05/11        ";
+
+#include "back.h"
+
+static int     i, j, k;
+static char    ln[60];
+
+wrboard ()  {
+       register int    l;
+       static char     bl[] =
+               "|                       |   |                       |\n";
+       static char     sv[] =
+               "|                       |   |                       |    \n";
+
+       fixtty (noech);
+       clear();
+
+       if (tflag)  {
+               fboard();
+               goto lastline;
+       }
+
+       writel ("_____________________________________________________\n");
+       writel (bl);
+       strcpy (ln,bl);
+       for (j = 1; j < 50; j += 4) {
+               k = j/4+(j > 24? 12: 13);
+               ln[j+1] = k%10+'0';
+               ln[j] = k/10+'0';
+               if (j == 21)
+                       j += 4;
+       }
+       writel (ln);
+       for (i = 0; i < 5; i++) {
+               strcpy (ln,sv);
+               for (j = 1; j < 50; j += 4) {
+                       k = j/4+(j > 24? 12: 13);
+                       wrbsub ();
+                       if (j == 21)
+                               j += 4;
+               }
+               if (-board[25] > i)
+                       ln[26] = 'w';
+               if (-board[25] > i+5)
+                       ln[25] = 'w';
+               if (-board[25] > i+10)
+                       ln[27] = 'w';
+               l = 53;
+               if (off[1] > i || (off[1] < 0 && off[1]+15 > i))  {
+                       ln[54] = 'r';
+                       l = 55;
+               }
+               if (off[1] > i+5 || (off[1] < 0 && off[1]+15 > i+5))  {
+                       ln[55] = 'r';
+                       l = 56;
+               }
+               if (off[1] > i+10 || (off[1] < 0 && off[1]+15 > i+10))  {
+                       ln[56] = 'r';
+                       l = 57;
+               }
+               ln[l++] = '\n';
+               ln[l] = '\0';
+               writel (ln);
+       }
+       strcpy (ln,bl);
+       ln[25] = 'B';
+       ln[26] = 'A';
+       ln[27] = 'R';
+       writel (ln);
+       strcpy (ln,sv);
+       for (i = 4; i > -1; i--) {
+               for (j = 1; j < 50; j += 4) {
+                       k = ((j > 24? 53: 49)-j)/4;
+                       wrbsub();
+                       if (j == 21)
+                               j += 4;
+               }
+               if (board[0] > i)
+                       ln[26] = 'r';
+               if (board[0] > i+5)
+                       ln[25] = 'r';
+               if (board[0] > i+10)
+                       ln[27] = 'r';
+               l = 53;
+               if (off[0] > i || (off[0] < 0 && off[0]+15 > i))  {
+                       ln[54] = 'w';
+                       l = 55;
+               }
+               if (off[0] > i+5 || (off[0] < 0 && off[0]+15 > i+5))  {
+                       ln[55] = 'w';
+                       l = 56;
+               }
+               if (off[0] > i+10 || (off[0] < 0 && off[0]+15 > i+10))  {
+                       ln[56] = 'w';
+                       l = 57;
+               }
+               ln[l++] = '\n';
+               ln[l] = '\0';
+               writel (ln);
+       }
+       strcpy (ln,bl);
+       for (j = 1; j < 50; j += 4) {
+               k = ((j > 24? 53: 49)-j)/4;
+               ln[j+1] = k%10+'0';
+               if (k > 9)
+                       ln[j] = k/10+'0';
+               if (j == 21)
+                       j += 4;
+       }
+       writel (ln);
+       writel ("|_______________________|___|_______________________|\n");
+
+lastline:
+       gwrite ();
+       if (tflag)
+               curmove (18,0);
+       else  {
+               writec ('\n');
+               writec ('\n');
+       }
+       fixtty(raw);
+}
+\f
+wrbsub () {
+       register int    m;
+       register char   d;
+
+       if (board[k] > 0)  {
+               m = board[k];
+               d = 'r';
+       } else {
+               m = -board[k];
+               d = 'w';
+       }
+       if (m>i)
+               ln[j+1] = d;
+       if (m>i+5)
+               ln[j] = d;
+       if (m>i+10)
+               ln[j+2] = d;
+}
diff --git a/usr/src/games/backgammon/check.c b/usr/src/games/backgammon/check.c
new file mode 100644 (file)
index 0000000..042b62f
--- /dev/null
@@ -0,0 +1,123 @@
+static char sccsid[] = "       check.c 4.1     82/05/11        ";
+
+#include "back.h"
+
+getmove ()  {
+       register int    i, c;
+
+       c = 0;
+       for (;;)  {
+               i = checkmove(c);
+
+               switch (i)  {
+               case -1:
+                       if (movokay(mvlim))  {
+                               if (tflag)
+                                       curmove (20,0);
+                               else
+                                       writec ('\n');
+                               for (i = 0; i < mvlim; i++)
+                                       if (h[i])
+                                               wrhit(g[i]);
+                               nexturn();
+                               if (*offopp == 15)
+                                       cturn *= -2;
+                               if (tflag && pnum)
+                                       bflag = pnum;
+                               return;
+                       }
+
+               case -4:
+               case 0:
+                       if (tflag)
+                               refresh();
+                       if (i != 0 && i != -4)
+                               break;
+                       if (tflag)
+                               curmove (20,0);
+                       else
+                               writec ('\n');
+                       writel (*Colorptr);
+                       if (i == -4)
+                               writel (" must make ");
+                       else
+                               writel (" can only make ");
+                       writec (mvlim+'0');
+                       writel (" move");
+                       if (mvlim > 1)
+                               writec ('s');
+                       writec ('.');
+                       writec ('\n');
+                       break;
+
+               case -3:
+                       if (quit())
+                               return;
+               }
+
+               if (! tflag)
+                       proll ();
+               else  {
+                       curmove (cturn == -1? 18: 19,39);
+                       cline ();
+                       c = -1;
+               }
+       }
+}
+\f
+movokay (mv)
+register int   mv;
+
+{
+       register int    i, m;
+
+       if (d0)
+               swap;
+
+       for (i = 0; i < mv; i++)  {
+
+               if (p[i] == g[i])  {
+                       moverr (i);
+                       curmove (20,0);
+                       writel ("Attempt to move to same location.\n");
+                       return (0);
+               }
+
+               if (cturn*(g[i]-p[i]) < 0)  {
+                       moverr (i);
+                       curmove (20,0);
+                       writel ("Backwards move.\n");
+                       return (0);
+               }
+
+               if (abs(board[bar]) && p[i] != bar)  {
+                       moverr (i);
+                       curmove (20,0);
+                       writel ("Men still on bar.\n");
+                       return (0);
+               }
+
+               if ( (m = makmove(i)) )  {
+                       moverr (i);
+                       switch (m)  {
+
+                       case 1:
+                               writel ("Move not rolled.\n");
+                               break;
+
+                       case 2:
+                               writel ("Bad starting position.\n");
+                               break;
+
+                       case 3:
+                               writel ("Destination occupied.\n");
+                               break;
+
+                       case 4:
+                               writel ("Can't remove men yet.\n");
+                       }
+                       return (0);
+               }
+       }
+       return (1);
+}
diff --git a/usr/src/games/backgammon/data.c b/usr/src/games/backgammon/data.c
new file mode 100644 (file)
index 0000000..0f60d53
--- /dev/null
@@ -0,0 +1,280 @@
+static char sccsid[] = "       data.c  4.1     82/05/11        ";
+
+#include "tutor.h"
+
+int    maxmoves = 23;
+
+char  *text0[] = {
+       "To start the game, I roll a 3, and you roll a 1.  This means",
+       "that I get to start first.  I move 8-5,6-5 since this makes a",
+       "new point and helps to trap your back men on 1.  You should be",
+       "able to do a similar move with your roll.",
+       0
+};
+
+char  *text1[] = {
+       "Now you shall see a move using doubles.  I just rolled double",
+       "5's.  I will move two men from position 13 to position 3.  The",
+       "notation for this is 13-8,13-8,8-3,8-3.  You will also roll dou-",
+       "bles, but you will be able to make a much stronger move.",
+       0
+};
+
+char  *text2[] = {
+       "Excellent!  As you can see, you are beginning to develop a wall",
+       "which is trapping my men on position 24.  Also, moving your back",
+       "men forward not only improves your board position safely, but it",
+       "thwarts my effort to make a wall.",
+       "",
+       "My roll now is 5 6.  Normally, I would use that roll to move from",
+       "position 24 to position 13 (24-18-13), but your new point prevents",
+       "that.  Instead, I am forced to move from 13 to 2, where my man is",
+       "open but cannot be hit.",
+       0
+};
+
+char  *text3[] = {
+       "As you can see, although you left a man open, it is a rela-",
+       "tively safe move to an advantageous position, which might help",
+       "you make a point later.  Only two rolls (4 5 or 5 4) will allow",
+       "me to hit you.  With an unprecedented amount of luck, I happen",
+       "to roll a 4 5 and hit you as just mentioned.",
+       0
+};
+
+char  *text4[] = {
+       "You're pretty lucky yourself, you know.  I follow by rolling 2 3",
+       "and moving 25-22,24-22, forming a new point.",
+       0
+};
+
+char  *text5[] = {
+       "Not a spectacular move, but a safe one.  I follow by rolling 6 1.",
+       "I decide to use this roll to move 22-16,16-17.  It leaves me with",
+       "one man still open, but the blot is farther back on the board, and",
+       "would suffer less of a loss by being hit.",
+       0
+};
+
+char  *text6[] = {
+       "By moving your two men from 17 to 20, you lessen my chance of",
+       "getting my man off the board.  In fact, the odds are 5 to 4",
+       "against me getting off.  I roll with the odds and helplessly",
+       "receive a 3 5.",
+       0
+};
+
+char  *text7[] = {
+       "Note that the blot on 7 cannot be hit unless I get off the bar",
+       "and have a 1 or a 6 left over, and doing so will leave two of",
+       "my men open.  Also, the blot on 16 cannot be hit at all!  With",
+       "a sigh of frustration, I roll double 6's and remain immobile.",
+       0
+};
+
+char  *text8[] = {
+       "See, you did not get hit and, you got to 'cover up' your open men.",
+       "Quite an accomplishment.  Finally, I get off the bar by rolling",
+       "6 2 and moving 25-23,23-17.",
+       0
+};
+
+char  *text9[] = {
+       "My venture off the bar did not last long.  However, I got lucky",
+       "and rolled double 1's, allowing me to move 0-1,1-2,15-14,15-14.",
+       0
+};
+
+char  *text10[] = {
+       "You are improving your position greatly and safely, and are well",
+       "on the way to winning the game.  I roll a 6 2 and squeak past",
+       "your back man.  Now the game becomes a race to the finish.",
+       0
+};
+
+char  *text11[] = {
+       "Now that it is merely a race, you are trying to get as many men",
+       "as possible into the inner table, so you can start removing them.",
+       "I roll a 3 4 and move my two men farthest back to position 11",
+       "(15-11,14-11).",
+       0
+};
+
+char  *text12[] = {
+       "The race is still on, and you have seem to be doing all right.",
+       "I roll 6 1 and move 14-8,13-12.",
+       0
+};
+
+char  *text13[] = {
+       "Notice that you get to remove men the instant you have all of",
+       "them at your inner table, even if it is the middle of a turn.",
+       "I roll 1 2 and move 13-11,12-11.",
+       0
+};
+
+char  *text14[] = {
+       "Although you could have removed a man, this move illustrates two",
+       "points:  1) You never have to remove men, and 2) You should try",
+       "to spread out your men on your inner table.  Since you have one",
+       "man on each position, you should be able to remove at least two",
+       "men next turn.  I roll 2 5 and move 8-6,11-6.",
+       0
+};
+
+char  *text15[] = {
+       "This time you were able to remove men.  I roll 3 4 and move",
+       "11-7,11-8.  The race continues.",
+       0
+};
+
+char  *text16[] = {
+       "More holes are opening up in your inner table, but you are",
+       "still very much ahead.  If we were doubling, you would have",
+       "doubled long ago.  I roll 2 6 and move 8-6,11-5.",
+       0
+};
+
+char  *text17[] = {
+       "It pays to spread out your men.  I roll 3 5 and move 7-4,8-3.",
+       0
+};
+
+char  *text18[] = {
+       "You can only remove some men, but you spread out more and",
+       "more, in order to be able to remove men more efficiently.",
+       "I roll double 3's, which help, but not that much.  I move",
+       "8-5,3-0,3-0,3-0.",
+       0
+};
+
+char  *text19[] = {
+       "I roll 1 4 and move 5-4,4-0.",
+       0
+};
+
+char  *text20[] = {
+       "You are now nicely spread out to win a game.  I roll 5 6 and",
+       "move 5-0,6-0.",
+       0
+};
+
+char  *text21[] = {
+       "Any minute now.  Just a few short steps from victory.  I roll",
+       "2 4 and move 6-4,4-0.",
+       0
+};
+
+char  *text22[] = {
+       "It looks pretty hopeless for me, but I play on, rolling 1 3 and",
+       "moving 4-3,3-0.",
+       0
+};
+
+char  *text23[] = {
+       "Congratulations!  You just won a game of backgammon against the",
+       "computer!  You will now be able to play a game, but remember,",
+       "when you start playing, that doubling will be enabled, which",
+       "will add another factor to the game...  Good luck!!",
+       "",
+       0
+};
+
+struct situatn  test[] = {
+       {
+               {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},
+               3, 1, {8,6,0,0}, {5,5,0,0}, 4, 2, &text0
+       },
+       {
+               {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},
+               5, 5, {13,13,8,8}, {8,8,3,3}, 6, 6, &text1
+       },
+       {
+               {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},
+               6, 5, {13,8,0,0}, {8,2,0,0}, 1, 2, &text2
+       },
+       {
+               {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},
+               4, 5, {24,20,0,0}, {20,15,0,0}, 2, 5, &text3
+       },
+       {
+               {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},
+               2, 3, {25,24,0,0}, {22,22,0,0}, 4, 1, &text4
+       },
+       {
+               {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},
+               6, 1, {22,16,0,0}, {16,15,0,0}, 3, 3, &text5
+       },
+       {
+               {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},
+               3, 5, {0,0,0,0}, {0,0,0,0}, 5, 4, &text6
+       },
+       {
+               {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},
+               6, 6, {0,0,0,0}, {0,0,0,0}, 3, 6, &text7
+       },
+       {
+               {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},
+               2, 6, {25,23,0,0}, {23,17,0,0}, 5, 1, &text8
+       },
+       {
+               {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},
+               1, 1, {25,24,15,15}, {24,23,14,14}, 4, 6, &text9
+       },
+       {
+               {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},
+               6, 2, {23,17,0,0}, {17,15,0,0}, 1, 3, &text10
+       },
+       {
+               {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},
+               4, 3, {15,14,0,0}, {11,11,0,0}, 5, 3, &text11
+       },
+       {
+               {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},
+               6, 1, {14,13,0,0}, {8,12,0,0}, 4, 4, &text12
+       },
+       {
+               {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},
+               2, 1, {13,12,0,0}, {11,11,0,0}, 2, 1, &text13
+       },
+       {
+               {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},
+               2, 5, {8,11,0,0}, {6,6,0,0}, 6, 3, &text14
+       },
+       {
+               {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},
+               4, 3, {11,11,0,0}, {7,8,0,0}, 2, 5, &text15
+       },
+       {
+               {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},
+               2, 6, {8,11,0,0}, {6,5,0,0}, 6, 1, &text16
+       },
+       {
+               {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},
+               5, 3, {8,7,0,0}, {3,4,0,0}, 5, 2, &text17
+       },
+       {
+               {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},
+               3, 3, {8,3,3,3}, {5,0,0,0}, 1, 6, &text18
+       },
+       {
+               {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},
+               1, 4, {4,5,0,0}, {0,4,0,0}, 2, 3, &text19
+       },
+       {
+               {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},
+               5, 6, {6,5,0,0}, {0,0,0,0}, 1, 4, &text20
+       },
+       {
+               {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},
+               2, 4, {4,6,0,0}, {0,4,0,0}, 6, 2, &text21
+       },
+       {
+               {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},
+               3, 1, {4,3,0,0}, {3,0,0,0}, 4, 3, &text22
+       },
+       {
+               {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},
+               0, 0, {0,0,0,0}, {0,0,0,0}, 0, 0, &text23
+       }
+};
diff --git a/usr/src/games/backgammon/extra.c b/usr/src/games/backgammon/extra.c
new file mode 100644 (file)
index 0000000..161202f
--- /dev/null
@@ -0,0 +1,218 @@
+static char sccsid[] = "       extra.c 4.1     82/05/11        ";
+
+#include "back.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+FILE   *trace;
+#endif
+
+/*
+ * dble()
+ *     Have the current player double and ask opponent to accept.
+ */
+
+dble ()  {
+       register int    resp;                   /* response to y/n */
+
+       for (;;)  {
+               writel (" doubles.");           /* indicate double */
+
+               if (cturn == -pnum)  {          /* see if computer accepts */
+                       if (dblgood())  {           /* guess not */
+                               writel ("  Declined.\n");
+                               nexturn();
+                               cturn *= -2;        /* indicate loss */
+                               return;
+                       } else  {                   /* computer accepts */
+                               writel ("  Accepted.\n");
+                               gvalue *= 2;        /* double game value */
+                               dlast = cturn;
+                               if (tflag)
+                                       gwrite();
+                               return;
+                       }
+               }
+
+                                               /* ask if player accepts */
+               writel ("  Does ");
+               writel (cturn == 1? color[2]: color[3]);
+               writel (" accept?");
+
+                                               /* get response from yorn,
+                                                * a "2" means he said "p"
+                                                * for print board. */
+               if ((resp = yorn ('R')) == 2)  {
+                       writel ("  Reprint.\n");
+                       buflush();
+                       wrboard();
+                       writel (*Colorptr);
+                       continue;
+               }
+
+                                               /* check response */
+               if (resp)  {
+                                                   /* accepted */
+                       gvalue *= 2;
+                       dlast = cturn;
+                       if (tflag)
+                               gwrite();
+                       return;
+               }
+
+               nexturn ();                     /* declined */
+               cturn *= -2;
+               return;
+       }
+}
+\f
+/*
+ * dblgood ()
+ *     Returns 1 if the computer would double in this position.  This
+ * is not an exact science.  The computer will decline a double that he
+ * would have made.  Accumulated judgments are kept in the variable n,
+ * which is in "pips", i.e., the position of each man summed over all
+ * men, with opponent's totals negative.  Thus, n should have a positive
+ * value of 7 for each move ahead, or a negative value of 7 for each one
+ * behind.
+ */
+
+dblgood ()  {
+       register int    n;                      /* accumulated judgment */
+       register int    OFFC = *offptr;         /* no. of computer's men off */
+       register int    OFFO = *offopp;         /* no. of player's men off */
+
+#ifdef DEBUG
+       register int    i;
+       if (trace == NULL)
+               trace = fopen ("bgtrace","w");
+#endif
+
+                                               /* get real pip value */
+       n = eval()*cturn;
+#ifdef DEBUG
+       fputs ("\nDoubles:\nBoard: ",trace);
+       for (i = 0; i < 26; i++)
+               fprintf (trace," %d",board[i]);
+       fprintf (trace,"\n\tpip = %d, ",n);
+#endif
+
+                                               /* below adjusts pip value
+                                                * according to position
+                                                * judgments */
+
+                                               /* check men moving off
+                                                * board */
+       if (OFFC > -15 || OFFO > -15)  {
+               if (OFFC < 0 && OFFO < 0)  {
+                       OFFC += 15;
+                       OFFO += 15;
+                       n +=((OFFC-OFFO)*7)/2;
+               } else if (OFFC < 0)  {
+                       OFFC += 15;
+                       n -= OFFO*7/2;
+               } else if (OFFO < 0)  {
+                       OFFO += 15;
+                       n += OFFC*7/2;
+               }
+               if (OFFC < 8 && OFFO > 8)
+                       n -= 7;
+               if (OFFC < 10 && OFFO > 10)
+                       n -= 7;
+               if (OFFC < 12 && OFFO > 12)
+                       n -= 7;
+               if (OFFO < 8 && OFFC > 8)
+                       n += 7;
+               if (OFFO < 10 && OFFC > 10)
+                       n += 7;
+               if (OFFO < 12 && OFFC > 12)
+                       n += 7;
+               n += ((OFFC-OFFO)*7)/2;
+       }
+
+#ifdef DEBUG
+       fprintf (trace,"off = %d, ",n);
+#endif
+
+                                               /* see if men are trapped */
+       n -= freemen(bar);
+       n += freemen(home);
+       n += trapped(home,-cturn);
+       n -= trapped(bar,cturn);
+
+#ifdef DEBUG
+       fprintf (trace,"free = %d\n",n);
+       fprintf (trace,"\tOFFC = %d, OFFO = %d\n",OFFC,OFFO);
+       fflush (trace);
+#endif
+
+                                               /* double if 2-3 moves ahead */
+       if (n > 10+rnum(7))
+               return(1);
+       return (0);
+}
+\f
+freemen (b)
+int    b;
+
+{
+       register int    i, inc, lim;
+
+       odds(0,0,0);
+       if (board[b] == 0)
+               return (0);
+       inc = (b == 0? 1: -1);
+       lim = (b == 0? 7: 18);
+       for (i = b+inc; i != lim; i += inc)
+               if (board[i]*inc < -1)
+                       odds(abs(b-i),0,abs(board[b]));
+       if (abs(board[b]) == 1)
+               return ((36-count())/5);
+       return (count()/5);
+}
+\f
+trapped (n,inc)
+int    n, inc;
+
+{
+       register int    i, j, k;
+       int             c, l, ct;
+
+       ct = 0;
+       l = n+7*inc;
+       for (i = n+inc; i != l; i += inc)  {
+               odds (0,0,0);
+               c = abs(i-l);
+               if (board[i]*inc > 0)  {
+                       for (j = c; j < 13; j++)
+                               if (board[i+inc*j]*inc < -1)  {
+                                       if (j < 7)
+                                               odds (j,0,1);
+                                       for (k = 1; k < 7 && k < j; k++)
+                                               if (j-k < 7)
+                                                       odds (k,j-k,1);
+                               }
+                       ct += abs(board[i])*(36-count());
+               }
+       }
+       return (ct/5);
+}
+\f
+eval ()  {
+
+       register int    i, j;
+
+       for (j = i = 0; i < 26; i++)
+               j += (board[i] >= 0 ? i*board[i] : (25-i)*board[i]);
+
+       if (off[1] >= 0)
+               j += 25*off[1];
+       else
+               j += 25*(off[1]+15);
+
+       if (off[0] >= 0)
+               j -= 25*off[0];
+       else
+               j -= 25*(off[0]+15);
+       return (j);
+}
diff --git a/usr/src/games/backgammon/init.c b/usr/src/games/backgammon/init.c
new file mode 100644 (file)
index 0000000..257af4c
--- /dev/null
@@ -0,0 +1,30 @@
+static char sccsid[] = "       init.c  4.1     82/05/11        ";
+
+#include <sgtty.h>
+
+/*
+ * variable initialization.
+ */
+
+                               /* name of executable object programs */
+char   EXEC[] = "/usr/games/backgammon";
+char   TEACH[] = "/usr/games/teachgammon";
+
+int    pnum    = 2;            /* color of player:
+                                       -1 = white
+                                        1 = red
+                                        0 = both
+                                        2 = not yet init'ed */
+int    acnt    = 0;            /* length of args */
+int    aflag   = 1;            /* flag to ask for rules or instructions */
+int    bflag   = 0;            /* flag for automatic board printing */
+int    cflag   = 0;            /* case conversion flag */
+int    hflag   = 1;            /* flag for cleaning screen */
+int    mflag   = 0;            /* backgammon flag */
+int    raflag  = 0;            /* 'roll again' flag for recovered game */
+int    rflag   = 0;            /* recovered game flag */
+int    tflag   = 0;            /* cursor addressing flag */
+int    iroll   = 0;            /* special flag for inputting rolls */
+int    rfl     = 0;
+
+char   *color[] = {"White","Red","white","red"};
diff --git a/usr/src/games/backgammon/move.c b/usr/src/games/backgammon/move.c
new file mode 100644 (file)
index 0000000..e298387
--- /dev/null
@@ -0,0 +1,516 @@
+static char sccsid[] = "       move.c  4.1     82/05/11        ";
+
+#include "back.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+FILE   *trace;
+static char    tests[20];
+#endif
+
+struct BOARD  {                                /* structure of game position */
+       int     b_board[26];                    /* board position */
+       int     b_in[2];                        /* men in */
+       int     b_off[2];                       /* men off */
+       int     b_st[4], b_fn[4];               /* moves */
+
+       struct BOARD    *b_next;                /* forward queue pointer */
+};
+
+struct BOARD *freeq = -1;
+struct BOARD *checkq = -1;
+struct BOARD *bsave();
+struct BOARD *nextfree();
+
+                                       /* these variables are values for the
+                                        * candidate move */
+static int     ch;                             /* chance of being hit */
+static int     op;                             /* computer's open men */
+static int     pt;                             /* comp's protected points */
+static int     em;                             /* farthest man back */
+static int     frc;                            /* chance to free comp's men */
+static int     frp;                            /* chance to free pl's men */
+
+                                       /* these values are the values for the
+                                        * move chosen (so far) */
+static int     chance;                         /* chance of being hit */
+static int     openmen;                        /* computer's open men */
+static int     points;                         /* comp's protected points */
+static int     endman;                         /* farthest man back */
+static int     barmen;                         /* men on bar */
+static int     menin;                          /* men in inner table */
+static int     menoff;                         /* men off board */
+static int     oldfrc;                         /* chance to free comp's men */
+static int     oldfrp;                         /* chance to free pl's men */
+
+static int     cp[5];                          /* candidate start position */
+static int     cg[5];                          /* candidate finish position */
+
+static int     race;                           /* game reduced to a race */
+\f
+move (okay)
+int    okay;                                   /* zero if first move */
+{
+       register int    i;              /* index */
+       register int    l;              /* last man */
+
+       if (okay)  {
+                                               /* see if comp should double */
+               if (gvalue < 64 && dlast != cturn && dblgood())  {
+                       writel (*Colorptr);
+                       dble();                     /* double */
+                                                   /* return if declined */
+                       if (cturn != 1 && cturn != -1)
+                               return;
+               }
+               roll();
+       }
+
+       race = 0;
+       for (i = 0; i < 26; i++)  {
+               if (board[i] < 0)
+                       l = i;
+       }
+       for (i = 0; i < l; i++)  {
+               if (board[i] > 0)
+                       break;
+       }
+       if (i == l)
+               race = 1;
+
+                                               /* print roll */
+       if (tflag)
+               curmove (cturn == -1? 18: 19,0);
+       writel (*Colorptr);
+       writel (" rolls ");
+       writec (D0+'0');
+       writec (' ');
+       writec (D1+'0');
+                                               /* make tty interruptable
+                                                * while thinking */
+       if (tflag)
+               cline();
+       fixtty (noech);
+
+                                               /* find out how many moves */
+       mvlim = movallow();
+       if (mvlim == 0)  {
+               writel (" but cannot use it.\n");
+               nexturn();
+               fixtty (raw);
+               return;
+       }
+
+                                               /* initialize */
+       for (i = 0; i < 4; i++)
+               cp[i] = cg[i] = 0;
+
+                                               /* strategize */
+       trymove (0,0);
+       pickmove();
+
+                                               /* print move */
+       writel (" and moves ");
+       for (i = 0; i < mvlim; i++)  {
+               if (i > 0)
+                       writec (',');
+               wrint (p[i] = cp[i]);
+               writec ('-');
+               wrint (g[i] = cg[i]);
+               makmove (i);
+       }
+       writec ('.');
+
+                                               /* print blots hit */
+       if (tflag)
+               curmove (20,0);
+       else
+               writec ('\n');
+       for (i = 0; i < mvlim; i++)
+               if (h[i])
+                       wrhit(g[i]);
+                                               /* get ready for next move */
+       nexturn();
+       if (!okay)  {
+               buflush();
+               sleep (3);
+       }
+       fixtty (raw);                           /* no more tty interrupt */
+}
+\f
+trymove (mvnum,swapped)
+register int   mvnum;                          /* number of move (rel zero) */
+int            swapped;                        /* see if swapped also tested */
+
+{
+       register int    pos;                    /* position on board */
+       register int    rval;                   /* value of roll */
+
+                                               /* if recursed through all dice
+                                                * values, compare move */
+       if (mvnum == mvlim)  {
+               binsert (bsave());
+               return;
+       }
+
+                                               /* make sure dice in always
+                                                * same order */
+       if (d0 == swapped)
+               swap;
+                                               /* choose value for this move */
+       rval = dice[mvnum != 0];
+
+                                               /* find all legitimate moves */
+       for (pos = bar; pos != home; pos += cturn)  {
+                                               /* fix order of dice */
+               if (d0 == swapped)
+                       swap;
+                                               /* break if stuck on bar */
+               if (board[bar] != 0 && pos != bar)
+                       break;
+                                               /* on to next if not occupied */
+               if (board[pos]*cturn <= 0)
+                       continue;
+                                               /* set up arrays for move */
+               p[mvnum] = pos;
+               g[mvnum] = pos+rval*cturn;
+               if (g[mvnum]*cturn >= home)  {
+                       if (*offptr < 0)
+                               break;
+                       g[mvnum] = home;
+               }
+                                               /* try to move */
+               if (makmove (mvnum))
+                       continue;
+               else
+                       trymove (mvnum+1,2);
+                                               /* undo move to try another */
+               backone (mvnum);
+       }
+
+                                               /* swap dice and try again */
+       if ((!swapped) && D0 != D1)
+               trymove (0,1);
+}
+\f
+struct BOARD *
+bsave ()  {
+       register int    i;              /* index */
+       struct BOARD    *now;           /* current position */
+
+       now = nextfree ();              /* get free BOARD */
+
+                                       /* store position */
+       for (i = 0; i < 26; i++)
+               now->b_board[i] = board[i];
+       now->b_in[0] = in[0];
+       now->b_in[1] = in[1];
+       now->b_off[0] = off[0];
+       now->b_off[1] = off[1];
+       for (i = 0; i < mvlim; i++)  {
+               now->b_st[i] = p[i];
+               now->b_fn[i] = g[i];
+       }
+       return (now);
+}
+\f
+binsert (new)
+struct BOARD   *new;                                   /* item to insert */
+{
+       register struct BOARD   *p = checkq;            /* queue pointer */
+       register int            result;                 /* comparison result */
+
+       if (p == -1)  {                         /* check if queue empty */
+               checkq = p = new;
+               p->b_next = -1;
+               return;
+       }
+
+       result = bcomp (new,p);                 /* compare to first element */
+       if (result < 0)  {                              /* insert in front */
+               new->b_next = p;
+               checkq = new;
+               return;
+       }
+       if (result == 0)  {                             /* duplicate entry */
+               mvcheck (p,new);
+               makefree (new);
+               return;
+       }
+
+       while (p->b_next != -1)  {              /* traverse queue */
+               result = bcomp (new,p->b_next);
+               if (result < 0)  {                      /* found place */
+                       new->b_next = p->b_next;
+                       p->b_next = new;
+                       return;
+               }
+               if (result == 0)  {                     /* duplicate entry */
+                       mvcheck (p->b_next,new);
+                       makefree (new);
+                       return;
+               }
+               p = p->b_next;
+       }
+                                               /* place at end of queue */
+       p->b_next = new;
+       new->b_next = -1;
+}
+\f
+bcomp (a,b)
+struct BOARD   *a;
+struct BOARD   *b;
+{
+       register int    *aloc = a->b_board;     /* pointer to board a */
+       register int    *bloc = b->b_board;     /* pointer to board b */
+       register int    i;                      /* index */
+       int             result;                 /* comparison result */
+
+       for (i = 0; i < 26; i++)  {             /* compare boards */
+               result = cturn*(aloc[i]-bloc[i]);
+               if (result)
+                       return (result);                /* found inequality */
+       }
+       return (0);                             /* same position */
+}
+\f
+mvcheck (incumbent,candidate)
+register struct BOARD  *incumbent;
+register struct BOARD  *candidate;
+{
+       register int    i;
+       register int    result;
+
+       for (i = 0; i < mvlim; i++)  {
+               result = cturn*(candidate->b_st[i]-incumbent->b_st[i]);
+               if (result > 0)
+                       return;
+               if (result < 0)
+                       break;
+       }
+       if (i == mvlim)
+               return;
+       for (i = 0; i < mvlim; i++)  {
+               incumbent->b_st[i] = candidate->b_st[i];
+               incumbent->b_fn[i] = candidate->b_fn[i];
+       }
+}
+\f
+makefree (dead)
+struct BOARD   *dead;                  /* dead position */
+{
+       dead->b_next = freeq;                   /* add to freeq */
+       freeq = dead;
+}
+
+struct BOARD *
+nextfree ()  {
+       struct BOARD    *new;
+
+       if (freeq == -1)  {
+               new = calloc (1,sizeof (struct BOARD));
+               if (new == 0)  {
+                       writel ("\nOut of memory\n");
+                       getout();
+               }
+               new->b_next = -1;
+               return (new);
+       }
+
+       new = freeq;
+       freeq = freeq->b_next;
+}
+\f
+pickmove ()  {
+                                               /* current game position */
+       register struct BOARD   *now = bsave();
+       register struct BOARD   *next;          /* next move */
+
+#ifdef DEBUG
+       if (trace == NULL)
+               trace = fopen ("bgtrace","w");
+       fprintf (trace,"\nRoll:  %d %d%s\n",D0,D1,race? " (race)": "");
+       fflush (trace);
+#endif
+       do  {                           /* compare moves */
+               bcopy (checkq);
+               next = checkq->b_next;
+               makefree (checkq);
+               checkq = next;
+               movcmp();
+       } while (checkq != -1);
+
+       bcopy (now);
+}
+\f
+bcopy (s)
+register struct BOARD  *s;                     /* game situation */
+{
+       register int    i;                      /* index */
+
+       for (i = 0; i < 26; i++)
+               board[i] = s->b_board[i];
+       for (i = 0; i < 2; i++)  {
+               in[i] = s->b_in[i];
+               off[i] = s->b_off[i];
+       }
+       for (i = 0; i < mvlim; i++)  {
+               p[i] = s->b_st[i];
+               g[i] = s->b_fn[i];
+       }
+}
+\f
+movcmp ()  {
+       register int    i;
+       register int    c;
+
+#ifdef DEBUG
+       if (trace == NULL)
+               trace = fopen ("bgtrace","w");
+#endif
+
+       odds (0,0,0);
+       if (!race)  {
+               ch = op = pt = 0;
+               for (i = 1; i < 25; i++)  {
+                       if (board[i] == cturn)
+                               ch = canhit (i,1);
+                               op += abs (bar-i);
+               }
+               for (i = bar+cturn; i != home; i += cturn)
+                       if (board[i]*cturn > 1)
+                               pt += abs(bar-i);
+               frc = freemen (bar)+trapped (bar,cturn);
+               frp = freemen (home)+trapped (home,-cturn);
+       }
+       for (em = bar; em != home; em += cturn)
+               if (board[em]*cturn > 0)
+                       break;
+       em = abs(home-em);
+#ifdef DEBUG
+       fputs ("Board: ",trace);
+       for (i = 0; i < 26; i++)
+               fprintf (trace, " %d",board[i]);
+       if (race)
+               fprintf (trace,"\n\tem = %d\n",em);
+       else
+               fprintf (trace,
+                       "\n\tch = %d, pt = %d, em = %d, frc = %d, frp = %d\n",
+                       ch,pt,em,frc,frp);
+       fputs ("\tMove: ",trace);
+       for (i = 0; i < mvlim; i++)
+               fprintf (trace," %d-%d",p[i],g[i]);
+       fputs ("\n",trace);
+       fflush (trace);
+       strcpy (tests,"");
+#endif
+       if ((cp[0] == 0 && cg[0] == 0) || movegood())  {
+#ifdef DEBUG
+               fprintf (trace,"\t[%s] ... wins.\n",tests);
+               fflush (trace);
+#endif
+               for (i = 0; i < mvlim; i++)  {
+                       cp[i] = p[i];
+                       cg[i] = g[i];
+               }
+               if (!race)  {
+                       chance = ch;
+                       openmen = op;
+                       points = pt;
+                       endman = em;
+                       barmen = abs(board[home]);
+                       oldfrc = frc;
+                       oldfrp = frp;
+               }
+               menin = *inptr;
+               menoff = *offptr;
+       }
+#ifdef DEBUG
+       else  {
+               fprintf (trace,"\t[%s] ... loses.\n",tests);
+               fflush (trace);
+       }
+#endif
+}
+\f
+movegood ()  {
+       register int    n;
+
+       if (*offptr == 15)
+               return (1);
+       if (menoff == 15)
+               return (0);
+       if (race)  {
+#ifdef DEBUG
+               strcat (tests,"o");
+#endif
+               if (*offptr-menoff)
+                       return (*offptr > menoff);
+#ifdef DEBUG
+               strcat (tests,"e");
+#endif
+               if (endman-em)
+                       return (endman > em);
+#ifdef DEBUG
+               strcat (tests,"i");
+#endif
+               if (menin == 15)
+                       return (0);
+               if (*inptr == 15)
+                       return (1);
+#ifdef DEBUG
+               strcat (tests,"i");
+#endif
+               if (*inptr-menin)
+                       return (*inptr > menin);
+               return (rnum(2));
+       } else  {
+               n = barmen-abs(board[home]);
+#ifdef DEBUG
+               strcat (tests,"c");
+#endif
+               if (abs(chance-ch)+25*n > rnum(150))
+                       return (n? (n < 0): (ch < chance));
+#ifdef DEBUG
+               strcat (tests,"o");
+#endif
+               if (*offptr-menoff)
+                       return (*offptr > menoff);
+#ifdef DEBUG
+               strcat (tests,"o");
+#endif
+               if (abs(openmen-op) > 7+rnum(12))
+                       return (openmen > op);
+#ifdef DEBUG
+               strcat (tests,"b");
+#endif
+               if (n)
+                       return (n < 0);
+#ifdef DEBUG
+               strcat (tests,"e");
+#endif
+               if (abs(endman-em) > rnum(2))
+                       return (endman > em);
+#ifdef DEBUG
+               strcat (tests,"f");
+#endif
+               if (abs(frc-oldfrc) > rnum(2))
+                       return (frc < oldfrc);
+#ifdef DEBUG
+               strcat (tests,"p");
+#endif
+               if (abs(n = pt-points) > rnum(4))
+                       return (n > 0);
+#ifdef DEBUG
+               strcat (tests,"i");
+#endif
+               if (*inptr-menin)
+                       return (*inptr > menin);
+#ifdef DEBUG
+               strcat (tests,"f");
+#endif
+               if (abs(frp-oldfrp) > rnum(2))
+                       return (frp > oldfrp);
+               return (rnum(2));
+       }
+}
diff --git a/usr/src/games/backgammon/odds.c b/usr/src/games/backgammon/odds.c
new file mode 100644 (file)
index 0000000..e9cc53a
--- /dev/null
@@ -0,0 +1,78 @@
+static char sccsid[] = "       odds.c  4.1     82/05/11        ";
+
+#include "back.h"
+
+odds (r1,r2,val)
+register int   r1;
+int            r2, val;
+{
+       register int    i, j;
+
+       if (r1 == 0)  {
+               for (i = 0; i < 6; i++)  
+                       for (j = 0; j < 6; j++)
+                               table[i][j] = 0;
+               return;
+       } else  {
+               r1--;
+               if (r2-- == 0)
+                       for (i = 0; i < 6; i++)  {
+                               table[i][r1] += val;
+                               table[r1][i] += val;
+                       }
+               else  {
+                       table[r2][r1] += val;
+                       table[r1][r2] += val;
+               }
+       }
+}
+
+count ()  {
+       register int    i;
+       register int    j;
+       register int    total;
+
+       total = 0;
+       for (i = 0; i < 6; i++)
+               for (j = 0; j < 6; j++)
+                       total += table[i][j];
+       return (total);
+}
+\f
+canhit (i,c)
+int    i, c;
+
+{
+       register int    j, k, b;
+       int             a, d, diff, place, addon, menstuck;
+
+       if (c == 0)
+               odds (0,0,0);
+       if (board[i] > 0)  {
+               a = -1;
+               b = 25;
+       } else  {
+               a = 1;
+               b = 0;
+       }
+       place = abs (25-b-i);
+       menstuck = abs (board[b]);
+       for (j = b; j != i; j += a)  {
+               if (board[j]*a > 0)  {
+                       diff = abs(j-i);
+                       addon = place+((board[j]*a > 2 || j == b)? 5: 0);
+                       if ((j == b && menstuck == 1) &&
+                           (j != b && menstuck == 0))
+                               for (k = 1; k < diff; k++)
+                                       if (k < 7 && diff-k < 7 &&
+                                           (board[i+a*k]*a >= 0 ||
+                                           board[i+a*(diff-k)] >= 0))
+                                               odds (k,diff-k,addon);
+                       if ((j == b || menstuck < 2) && diff < 7)
+                               odds (diff,0,addon);
+               }
+               if (j == b && menstuck > 1)
+                       break;
+       }
+       return (count());
+}
diff --git a/usr/src/games/backgammon/one.c b/usr/src/games/backgammon/one.c
new file mode 100644 (file)
index 0000000..431084a
--- /dev/null
@@ -0,0 +1,134 @@
+static char sccsid[] = "       one.c   4.1     82/05/11        ";
+
+#include "back.h"
+
+makmove (i)
+register int   i;
+{
+       register int    n, d;
+       int             max;
+
+       d = d0;
+       n = abs(g[i]-p[i]);
+       max = (*offptr < 0? 7: last());
+       if (board[p[i]]*cturn <= 0)
+               return (checkd(d)+2);
+       if (g[i] != home && board[g[i]]*cturn < -1)
+               return (checkd(d)+3);
+       if (i || D0 == D1)  {
+               if (n == max? D1 < n: D1 != n)
+                       return (checkd(d)+1);
+       } else  {
+               if (n == max? D0 < n && D1 < n: D0 != n && D1 != n)
+                       return (checkd(d)+1);
+               if (n == max? D0 < n: D0 != n)  {
+                       if (d0)
+                               return (checkd(d)+1);
+                       swap;
+               }
+       }
+       if (g[i] == home && *offptr < 0)
+               return (checkd(d)+4);
+       h[i] = 0;
+       board[p[i]] -= cturn;
+       if (g[i] != home)  {
+               if (board[g[i]] == -cturn)  {
+                       board[home] -= cturn;
+                       board[g[i]] = 0;
+                       h[i] = 1;
+                       if (abs(bar-g[i]) < 7)  {
+                               (*inopp)--;
+                               if (*offopp >= 0)
+                                       *offopp -= 15;
+                       }
+               }
+               board[g[i]] += cturn;
+               if (abs(home-g[i]) < 7 && abs(home-p[i]) > 6)  {
+                       (*inptr)++;
+                       if (*inptr+*offptr == 0)
+                               *offptr += 15;
+               }
+       } else {
+               (*offptr)++;
+               (*inptr)--;
+       }
+       return (0);
+}
+\f
+moverr (i)
+register int   i;
+
+{
+       register int    j;
+
+       if (tflag)
+               curmove (20,0);
+       else
+               writec ('\n');
+       writel ("Error:  ");
+       for (j = 0; j <= i; j++)  {
+               wrint (p[j]);
+               writec ('-');
+               wrint (g[j]);
+               if (j < i)
+                       writec (',');
+       }
+       writel ("... ");
+       movback (i);
+}
+
+
+checkd (d)
+register int   d;
+
+{
+       if (d0 != d)
+               swap;
+       return (0);
+}
+
+last ()  {
+       register int    i;
+
+       for (i = home-6*cturn; i != home; i += cturn)
+               if (board[i]*cturn > 0)
+                       return (abs(home-i));
+}
+\f
+movback (i)
+register int   i;
+
+{
+       register int    j;
+
+       for (j = i-1; j >= 0; j--)
+               backone(j);
+}
+
+backone (i)
+register int   i;
+
+{
+       board[p[i]] += cturn;
+       if (g[i] != home)  {
+               board[g[i]] -= cturn;
+               if (abs(g[i]-home) < 7 && abs(p[i]-home) > 6)  {
+                       (*inptr)--;
+                       if (*inptr+*offptr < 15 && *offptr >= 0)
+                               *offptr -= 15;
+               }
+       } else  {
+               (*offptr)--;
+               (*inptr)++;
+       }
+       if (h[i])  {
+               board[home] += cturn;
+               board[g[i]] = -cturn;
+               if (abs(bar-g[i]) < 7)  {
+                       (*inopp)++;
+                       if (*inopp+*offopp == 0)
+                               *offopp += 15;
+               }
+       }
+}
diff --git a/usr/src/games/backgammon/table.c b/usr/src/games/backgammon/table.c
new file mode 100644 (file)
index 0000000..0325051
--- /dev/null
@@ -0,0 +1,273 @@
+static char sccsid[] = "       table.c 4.1     82/05/11        ";
+
+#include "back.h"
+
+char   *help2[] = {
+       "   Enter moves as <s>-<f> or <s>/<r> where <s> is the starting",
+       "position, <f> is the finishing position, and <r> is the roll.",
+       "Remember, each die roll must be moved separately.",
+       0
+};
+
+struct state   {
+       char    ch;
+       int     fcode;
+       int     newst;
+};
+
+struct state   atmata[] = {
+
+       'R', 1, 0,      '?', 7, 0,      'Q', 0, -3,     'B', 8, 25,
+       '9', 2, 25,     '8', 2, 25,     '7', 2, 25,     '6', 2, 25,
+       '5', 2, 25,     '4', 2, 25,     '3', 2, 25,     '2', 2, 19,
+       '1', 2, 15,     '0', 2, 25,     '.', 0, 0,      '9', 2, 25,
+       '8', 2, 25,     '7', 2, 25,     '6', 2, 25,     '5', 2, 25,
+
+       '4', 2, 25,     '3', 2, 25,     '2', 2, 25,     '1', 2, 25,
+       '0', 2, 25,     '/', 0, 32,     '-', 0, 39,     '.', 0, 0,
+       '/', 5, 32,     ' ', 6, 3,      ',', 6, 3,      '\n', 0, -1,
+       '6', 3, 28,     '5', 3, 28,     '4', 3, 28,     '3', 3, 28,
+       '2', 3, 28,     '1', 3, 28,     '.', 0, 0,      'H', 9, 61,
+
+       '9', 4, 61,     '8', 4, 61,     '7', 4, 61,     '6', 4, 61,
+       '5', 4, 61,     '4', 4, 61,     '3', 4, 61,     '2', 4, 53,
+       '1', 4, 51,     '0', 4, 61,     '.', 0, 0,      '9', 4, 61,
+       '8', 4, 61,     '7', 4, 61,     '6', 4, 61,     '5', 4, 61,
+       '4', 4, 61,     '3', 4, 61,     '2', 4, 61,     '1', 4, 61,
+
+       '0', 4, 61,     ' ', 6, 3,      ',', 6, 3,      '-', 5, 39,
+       '\n', 0, -1,    '.', 0, 0
+};
+
+checkmove (ist)
+
+int    ist;
+
+{
+       register int    j, n;
+       register char   c;
+       char            a;
+
+domove:
+       if (ist == 0)  {
+               if (tflag)
+                       curmove (curr,32);
+               else
+                       writel ("\t\t");
+               writel ("Move:  ");
+       }
+       ist = mvl = ncin = 0;
+       for (j = 0; j < 5; j++)
+               p[j] = g[j] = -1;
+
+dochar:
+       c = readc();
+
+       if (c == 'S')  {
+               raflag = 0;
+               save (1);
+               if (tflag)  {
+                       curmove (cturn == -1? 18: 19,39);
+                       ist = -1;
+                       goto domove;
+               } else  {
+                       proll ();
+                       ist = 0;
+                       goto domove;
+               }
+       }
+
+       if (c == tty.sg_erase && ncin > 0)  {
+               if (tflag)
+                       curmove (curr,curc-1);
+               else  {
+                       if (tty.sg_erase == '\010')
+                               writel ("\010 \010");
+                       else
+                               writec (cin[ncin-1]);
+               }
+               ncin--;
+               n = rsetbrd();
+               if (n == 0)  {
+                       n = -1;
+                       if (tflag)
+                               refresh();
+               }
+               if ((ist = n) > 0)
+                       goto dochar;
+               goto domove;
+       }
+
+       if (c == tty.sg_kill && ncin > 0)  {
+               if (tflag)  {
+                       refresh();
+                       curmove (curr,39);
+                       ist = -1;
+                       goto domove;
+               } else  if (tty.sg_erase == '\010')  {
+                       for (j = 0; j < ncin; j++)
+                               writel ("\010 \010");
+                       ist = -1;
+                       goto domove;
+               } else  {
+                       writec ('\\');
+                       writec ('\n');
+                       proll ();
+                       ist = 0;
+                       goto domove;
+               }
+       }
+
+       n = dotable(c,ist);
+       if (n >= 0)  {
+               cin[ncin++] = c;
+               if (n > 2)
+               if ((! tflag) || c != '\n')
+                       writec (c);
+               ist = n;
+               if (n)
+                       goto dochar;
+               else
+                       goto domove;
+       }
+
+       if (n == -1 && mvl >= mvlim)
+               return(0);
+       if (n == -1 && mvl < mvlim-1)
+               return(-4);
+
+       if (n == -6)  {
+               if (! tflag)  {
+                       if (movokay(mvl+1))  {
+                               wrboard();
+                               movback (mvl+1);
+                       }
+                       proll ();
+                       writel ("\t\tMove:  ");
+                       for (j = 0; j < ncin;)
+                               writec (cin[j++]);
+               } else  {
+                       if (movokay(mvl+1))  {
+                               refresh();
+                               movback (mvl+1);
+                       } else
+                               curmove (cturn == -1? 18:19,ncin+39);
+               }
+               ist = n = rsetbrd();
+               goto dochar;
+       }
+
+       if (n != -5)
+               return(n);
+       writec ('\007');
+       goto dochar;
+}
+\f
+dotable (c,i)
+char           c;
+register int   i;
+
+{
+       register int    a, j;
+       int             test;
+
+       test = (c == 'R');
+
+       while ( (a = atmata[i].ch) != '.')  {
+               if (a == c || (test && a == '\n'))  {
+                       switch  (atmata[i].fcode)  {
+
+                       case 1:
+                               wrboard();
+                               if (tflag)  {
+                                       curmove (cturn == -1? 18: 19,0);
+                                       proll ();
+                                       writel ("\t\t");
+                               } else
+                                       proll ();
+                               break;
+
+                       case 2:
+                               if (p[mvl] == -1)
+                                       p[mvl] = c-'0';
+                               else
+                                       p[mvl] = p[mvl]*10+c-'0';
+                               break;
+
+                       case 3:
+                               if (g[mvl] != -1)  {
+                                       if (mvl < mvlim)
+                                               mvl++;
+                                       p[mvl] = p[mvl-1];
+                               }
+                               g[mvl] = p[mvl]+cturn*(c-'0');
+                               if (g[mvl] < 0)
+                                       g[mvl] = 0;
+                               if (g[mvl] > 25)
+                                       g[mvl] = 25;
+                               break;
+
+                       case 4:
+                               if (g[mvl] == -1)
+                                       g[mvl] = c-'0';
+                               else
+                                       g[mvl] = g[mvl]*10+c-'0';
+                               break;
+
+                       case 5:
+                               if (mvl < mvlim)
+                                       mvl++;
+                               p[mvl] = g[mvl-1];
+                               break;
+
+                       case 6:
+                               if (mvl < mvlim)
+                                       mvl++;
+                               break;
+
+                       case 7:
+                               if (tflag)
+                                       curmove (20,0);
+                               else
+                                       writec ('\n');
+                               text (help2);
+                               if (tflag)  {
+                                       curmove (cturn == -1? 18: 19,39);
+                               } else  {
+                                       writec ('\n');
+                                       proll();
+                                       writel ("\t\tMove:  ");
+                               }
+                               break;
+
+                       case 8:
+                               p[mvl] = bar;
+                               break;
+
+                       case 9:
+                               g[mvl] = home;
+                       }
+
+                       if (! test || a != '\n')
+                               return (atmata[i].newst);
+                       else
+                               return (-6);
+               }
+
+               i++;
+       }
+
+       return (-5);
+}
+\f
+rsetbrd ()  {
+       register int    i, j, n;
+
+       n = 0;
+       mvl = 0;
+       for (i = 0; i < 4; i++)
+               p[i] = g[i] = -1;
+       for (j = 0; j < ncin; j++)
+               n = dotable (cin[j],n);
+       return (n);
+}
diff --git a/usr/src/games/backgammon/teach.c b/usr/src/games/backgammon/teach.c
new file mode 100644 (file)
index 0000000..ffda12d
--- /dev/null
@@ -0,0 +1,126 @@
+static char sccsid[] = "       teach.c 4.1     82/05/11        ";
+
+#include "back.h"
+
+char   *hello[];
+char   *list[];
+char   *intro1[];
+char   *intro2[];
+char   *moves[];
+char   *remove[];
+char   *hits[];
+char   *endgame[];
+char   *doubl[];
+char   *stragy[];
+char   *prog[];
+char   *lastch[];
+
+extern char    ospeed;                 /* tty output speed for termlib */
+
+char *helpm[] = {
+       "\nEnter a space or newline to roll, or",
+       "     b   to display the board",
+       "     d   to double",
+       "     q   to quit\n",
+       0
+};
+
+char *contin[] = {
+       "",
+       0
+};
+
+main (argc,argv)
+int    argc;
+char   **argv;
+
+{
+       register char   *s, *ts[];
+       register int    i;
+
+       signal (2,getout);
+       if (gtty (0,&tty) == -1)                        /* get old tty mode */
+               errexit ("teachgammon(gtty)");
+       old = tty.sg_flags;
+#ifdef V7
+       raw = ((noech = old & ~ECHO) | CBREAK);         /* set up modes */
+#else
+       raw = ((noech = old & ~ECHO) | RAW);            /* set up modes */
+#endif
+       ospeed = old.sg_ospeed;                         /* for termlib */
+       tflag = getcaps (getenv ("TERM"));
+#ifdef V7
+       while (*++argv != 0)
+#else
+       while (*++argv != -1)
+#endif
+               getarg (&argv);
+       if (tflag)  {
+               noech &= ~(CRMOD|XTABS);
+               raw &= ~(CRMOD|XTABS);
+               clear();
+       }
+       text (hello);
+       text (list);
+       i = text (contin);
+       if (i == 0)
+               i = 2;
+       init();
+       while (i)
+               switch (i)  {
+               
+               case 1:
+                       leave();
+               
+               case 2:
+                       if (i = text(intro1))
+                               break;
+                       wrboard();
+                       if (i = text(intro2))
+                               break;
+               
+               case 3:
+                       if (i = text(moves))
+                               break;
+               
+               case 4:
+                       if (i = text(remove))
+                               break;
+               
+               case 5:
+                       if (i = text(hits))
+                               break;
+               
+               case 6:
+                       if (i = text(endgame))
+                               break;
+               
+               case 7:
+                       if (i = text(doubl))
+                               break;
+               
+               case 8:
+                       if (i = text(stragy))
+                               break;
+               
+               case 9:
+                       if (i = text(prog))
+                               break;
+               
+               case 10:
+                       if (i = text(lastch))
+                               break;
+               }
+       tutor();
+}
+
+leave()  {
+       if (tflag)
+               clear();
+       else
+               writec ('\n');
+       fixtty(old);
+       execl (EXEC,"backgammon",args,"n",0);
+       writel ("Help! Backgammon program is missing\007!!\n");
+       exit (-1);
+}
diff --git a/usr/src/games/backgammon/text.c b/usr/src/games/backgammon/text.c
new file mode 100644 (file)
index 0000000..7f4b6d1
--- /dev/null
@@ -0,0 +1,97 @@
+static char sccsid[] = "       text.c  4.1     82/05/11        ";
+
+#include "back.h"
+
+char *instr[] = {
+    "    If you did not notice by now, this program reacts to things as",
+    "soon as you type them, without waiting for a newline.  This means that",
+    "the special characters RUBOUT, ESC, and CONTROL-D, will not perform",
+    "their special functions during most of this program.  The program",
+    "should usually stop when a RUBOUT is typed, but occasionally it will",
+    "ignore RUBOUTs until it is waiting for input.\n",
+    "    These instructions are presented in small chunks designed not to",
+    "roll off the top of your screen.  When the characters '-->' are print-",
+    "ed, no more data will be printed until a space or newline is typed.",
+    "In this way, you can finish one section before continuing to another.",
+    "Like this:",
+    "",
+    "    The two sides are colored 'red' and 'white.' The computer may play",
+    "one side, or if there are two players, the computer can merely act as",
+    "a gamekeeper, letting the players make the moves.  Once you tell the",
+    "computer what color(s) you want to play, the decision remains in ef-",
+    "fect until you quit the program, even if you play more than one game,",
+    "since the program keeps a running score.\n",
+    "    The program will prompt for a move in one of two ways.  If the",
+    "player has the opportunity to double, then merely his color will be",
+    "typed out.  The player can now do one of several things.  He can dou-",
+    "ble by typing a 'd', he can roll by typing a space (' ') or newline,",
+    "or if he is not sure, he can reprint the board by typing a 'r'.\n",
+    "    If the player cannot double, his roll will be thrust in front of",
+    "him, followed by the request 'Move:', asking for a move but not giving",
+    "him the chance to double.  He can still ask for the board by typing",
+    "'r'.  In either of these two states, the player can quit by typing 'q'",
+    "or save the game by typing 's'.  In either case, the player will be",
+    "asked to verify, in case there was some error.  The program then ends",
+    "immediately, after first saving the file if so requested.",
+    "",
+    "    A player can move one of his men using two forms of input.  The",
+    "first form is <s>-<f>, where <s> is the starting position, and <f> is",
+    "the finishing position of the player's man.  For example, if white",
+    "wanted to move a piece from position 13 to position 8, his move could",
+    "be entered as 13-8.  The second form is <s>/<r> where <s> is the",
+    "starting position, an <r> is the roll actually made.  Hence, white",
+    "could have entered as 13/5 instead of 13-8.\n",
+    "    A player must move each roll of the dice separately.  For example,",
+    "if a player rolled 4 3, and wanted to move from 13 to 6, he could",
+    "enter it as 13/4,9/3 or 13/3,10/4 or 13-10,10-6 or 13-9,9-6, but not",
+    "13-6.  The last two entries can be shortened to 13-10-6 and 13-9-6.",
+    "If you want to move more than one piece from the same position, such",
+    "as 13-10,13-9, you can abbreviate this using the <s>/<r> format as by",
+    "entering more than one <r>, or 13/34.  A player can use both forms for",
+    "the same roll, e.g. 13/3,13-9, and separates individual moves by ei-",
+    "ther a comma or a space.  The letter 'b' represents the bar, and the",
+    "letter 'h' represents a player's home.  You could also enter the",
+    "number that would be in the position of the bar, 25 or 0 as appropri-",
+    "ate.  Use a newline at the end of your moves for a turn.",
+    "",
+    "    As you type in your move, if a character does not make sense under",
+    "the above constrictions, a bell will sound instead of the character,",
+    "and it will be ignored.  You may kill lines and erase characters as",
+    "you would normally, but don't be surprised if they look different than",
+    "usual.  Also, if you have entered one or more of your rolls, and you",
+    "wish to see what the move looks like so far, type a 'r' to see what it",
+    "looks like.  This cannot be done in the middle of a move (e.g., after",
+    "a '-' or '/').  After the printing board, the program will go back to",
+    "inputting your move and you can backspace or kill just as if you had",
+    "just typed in your input.\n",
+    "    Now you should be ready to begin the game.  Good luck!",
+    "",
+    0};
+\f
+
+text (t)
+char   **t;
+
+{
+       register int    i;
+       register char   *s, *a;
+
+       fixtty (noech);
+       while (*t != 0)  {
+               s = a = *t;
+               for (i = 0; *a != '\0'; i--)
+                       a++;
+               if (i)  {
+                       writel (s);
+                       writec ('\n');
+               } else  {
+                       writel ("-->");
+                       fixtty (raw);
+                       while ((i = readc()) != ' ' && i != '\n');
+                       fixtty (noech);
+                       clear();
+               }
+               t++;
+       }
+       fixtty (raw);
+}
diff --git a/usr/src/games/backgammon/ttext1.c b/usr/src/games/backgammon/ttext1.c
new file mode 100644 (file)
index 0000000..ce6f3c7
--- /dev/null
@@ -0,0 +1,149 @@
+static char sccsid[] = "       ttext1.c        4.1     82/05/11        ";
+
+#include "back.h"
+
+char   *opts = " QIMRHEDSPT";
+char   *prompt = "-->";
+
+char *list[] = {
+    "\n\n\tI\tIntroduction to Backgammon",
+    "\tM\tMoves and Points",
+    "\tR\tRemoving Men from the Board",
+    "\tH\tHitting Blots",
+    "\tE\tEnding the Game and Scoring",
+    "\tD\tDoubling",
+    "\tS\tStrategy",
+    "\tP\tThe Program and How to Use It",
+    "\nalso, you can type:",
+    "\t?\tto get this list",
+    "\tQ\tto go start playing",
+    "\tT\tto go straight to the tutorial",
+    0
+};
+
+char   *hello[] = {
+    "\n\032   These rules consist of text describing how to play Backgammon",
+    "followed by a tutorial session where you play a practice game",
+    "against the computer.  When using this program, think carefuly",
+    "before typing, since it reacts as soon as you type something.  In",
+    "addition, the program presents text output, such as these rules,",
+    "in small blocks that will not roll off the top of the screen.",
+    "Frequently, you will see the characters '-->' indicating that the",
+    "program is waiting for you to finish reading, and will continue",
+    "printing when you type a space or newline.  Also, the rules are",
+    "divided into sections, and although you should read them in or-",
+    "der, you can go directly to any of them by typing one of the fol-",
+    "lowing letters:",
+    "(Remember to hit a space or a newline to continue.)",
+    "",
+    0
+};
+
+char   *intro1[] = {
+    "\nIntroduction:",
+    "\n   Backgammon is a game involving the skill of two players and",
+    "the luck of two dice.  There are two players, red and white, and",
+    "each player gets fifteen men.  The object of the game is to re-",
+    "move all your men from the board before the opponent does.  The",
+    "board consists of twenty-four positions, a 'bar' and a 'home' for",
+    "each player.  It looks like this:",
+    "",
+    0};
+
+char   *intro2[] = {
+    "",
+    "\n   Although not indicated on the board, the players' homes are",
+    "located just to the right of the board.  A player's men are placed",
+    "there when they are removed from the board.  The board you just",
+    "saw was in it's initial position.  All games start with the board",
+    "looking like this.  Notice that red's pieces are represented by the",
+    "letter 'r' and white's pieces are represented by the letter 'w'.",
+    "Also, a position may have zero or more pieces on it, e.g.  posi-",
+    "tion 12 has five red pieces on it, while position 11 does not",
+    "have any pieces of either color.",
+    "",
+    0};
+\f
+char   *moves[] = {
+    "\nMoves and Points:",
+    "\n   Moves are made along the positions on the board according to",
+    "their numbers.  Red moves in the positive direction (clockwise",
+    "from 1 to 24), and white moves in the negative direction (coun-",
+    "terclockwise from 24 to 1).",
+    "\n   A turn consists of rolling the dice, and moving the number of",
+    "positions indicated on each die.  The two numbers can be used to",
+    "move one man the sum of the two rolls, or two men the number on",
+    "each individual die.  For example, if red rolled 6 3 at the start",
+    "of the game, he might move a man from 1 to 7 to 10, using both",
+    "dice for one man, or he might move two men from position 12, one",
+    "to 15 and one to 18.  (Red did not have to choose two men start-",
+    "ing from the same position.)  In addition, doubles are treated",
+    "specially in backgammon.  When a player rolls doubles, he gets to",
+    "move as if he had four dice instead of two.  For instance, if you",
+    "rolled double 2's, you could move one man eight positions, four",
+    "men two positions each, or any permutation in between.",
+    "",
+    "\n   However, there are certain limitations, called 'points.'  A",
+    "player has a point when he has two or more men on the same posi-",
+    "tion.  This gives him custody of that position, and his opponent",
+    "cannot place his men there, even if passing through on the way to",
+    "another position.  When a player has six points in a row, it is",
+    "called a 'wall,' since any of his opponent's men behind the wall",
+    "cannot pass it and are trapped, at least for the moment.  Notice",
+    "that this could mean that a player could not use part or all of",
+    "his roll.  However, he must use as much of his roll as possible.",
+    "",
+    0};
+
+char   *remove[] = {
+    "\nRemoving Men from the Board:",
+    "\n   The most important part of the game is removing men, since",
+    "that is how you win the game.  Once a man is removed, he stays",
+    "off the board for the duration of the game.  However, a player",
+    "cannot remove men until all his men are on his 'inner table,' or",
+    "the last six positions of the board (19-24 for red, 6-1 for",
+    "white).",
+    "\n   To get off the board, a player must roll the exact number to",
+    "get his man one position past the last position on the board, or",
+    "his 'home.'  Hence, if red wanted to remove a man from position",
+    "23, he would have to roll a 2, anything else would be used for",
+    "another man, or for another purpose.  However, there is one ex-",
+    "ception.  If the player rolling has no men far enough to move the",
+    "roll made, he may move his farthest man off the board.  For exam-",
+    "ple, if red's farthest man back was on position 21, he could re-",
+    "move men from that position if he rolled a 5 or a 6, as well as a",
+    "4.  Since he does not have men on 20 (where he could use a 5) or",
+    "on 19 (where he could use a 6), he can use these rolls for posi-",
+    "tion 21.  A player never has to remove men, but he must make as",
+    "many moves as possible.",
+    "",
+    0};
+\f
+char   *hits[] = {
+    "\nHitting Blots:",
+    "\n   Although two men on a position form an impenetrable point, a",
+    "lone man is not so secure.  Such a man is called a 'blot' and has",
+    "the potential of getting hit by an opposing man.  When a player's",
+    "blot is hit, he is placed on the bar, and the first thing that",
+    "player must do is move the man off the bar.  Such moves are",
+    "counted as if the bar is one position behind the first position",
+    "on the board.  Thus if red has a man on the bar and rolls 2 3, he",
+    "must move the man on the bar to position 2 or 3 before moving any",
+    "other man.  If white had points on positions 2 and 3, then red",
+    "would forfeit his turn.  Being on the bar is a very bad position,",
+    "for often a player can lose many turns trying to move off the",
+    "bar, as well as being set back the full distance of the board.",
+    "",
+    0};
+\f
+char   *endgame[] = {
+    "\nEnding the Game and Scoring:",
+    "\n   Winning a game usually wins one point, the normal value of a",
+    "game.  However, if the losing player has not removed any men yet,",
+    "then the winning player wins double the game value, called a",
+    "'gammon.'  If the losing player has a player on the bar or on the",
+    "winner's inner table, then the winner gets triple the game value,",
+    "which is called a 'backgammon.'  (So that's where the name comes",
+    "from!)",
+    "",
+    0};
diff --git a/usr/src/games/backgammon/tutor.c b/usr/src/games/backgammon/tutor.c
new file mode 100644 (file)
index 0000000..bed4e2d
--- /dev/null
@@ -0,0 +1,120 @@
+static char sccsid[] = "       tutor.c 4.1     82/05/11        ";
+
+#include "back.h"
+#include "tutor.h"
+
+extern int     maxmoves;
+extern char    *finis[];
+
+extern struct situatn  test[];
+
+static char    better[] = "That is a legal move, but there is a better one.\n";
+
+tutor ()  {
+       register int    i, j;
+
+       i = 0;
+       begscr = 18;
+       cturn = -1;
+       home = 0;
+       bar = 25;
+       inptr = &in[0];
+       inopp = &in[1];
+       offptr = &off[0];
+       offopp = &off[1];
+       Colorptr = &color[0];
+       colorptr = &color[2];
+       colen = 5;
+       wrboard();
+
+       while (1)  {
+               if (! brdeq(test[i].brd,board))  {
+                       if (tflag && curr == 23)
+                               curmove (18,0);
+                       writel (better);
+                       nexturn();
+                       movback (mvlim);
+                       if (tflag)  {
+                               refresh();
+                               clrest ();
+                       }
+                       if ((! tflag) || curr == 19)  {
+                               proll();
+                               writec ('\t');
+                       }
+                       else
+                               curmove (curr > 19? curr-2: curr+4,25);
+                       getmove();
+                       if (cturn == 0)
+                               leave();
+                       continue;
+               }
+               if (tflag)
+                       curmove (18,0);
+               text (*test[i].com);
+               if (! tflag)
+                       writec ('\n');
+               if (i == maxmoves)
+                       break;
+               D0 = test[i].roll1;
+               D1 = test[i].roll2;
+               d0 = 0;
+               mvlim = 0;
+               for (j = 0; j < 4; j++)  {
+                       if (test[i].mp[j] == test[i].mg[j])
+                               break;
+                       p[j] = test[i].mp[j];
+                       g[j] = test[i].mg[j];
+                       mvlim++;
+               }
+               if (mvlim)
+                       for (j = 0; j < mvlim; j++)
+                               if (makmove(j))
+                                       writel ("AARGH!!!\n");
+               if (tflag)
+                       refresh();
+               nexturn();
+               D0 = test[i].new1;
+               D1 = test[i].new2;
+               d0 = 0;
+               i++;
+               mvlim = movallow();
+               if (mvlim)  {
+                       if (tflag)
+                               clrest();
+                       proll();
+                       writec('\t');
+                       getmove();
+                       if (tflag)
+                               refresh();
+                       if (cturn == 0)
+                               leave();
+               }
+       }
+       leave();
+}
+
+clrest ()  {
+       register int    r, c, j;
+
+       r = curr;
+       c = curc;
+       for (j = r+1; j < 24; j++)  {
+               curmove (j,0);
+               cline();
+       }
+       curmove (r,c);
+}
+
+brdeq (b1,b2)
+register int  *b1, *b2;
+
+{
+       register int  *e;
+
+       e = b1+26;
+       while (b1 < e)
+               if (*b1++ != *b2++)
+                       return(0);
+       return(1);
+}
diff --git a/usr/src/games/backgammon/tutor.h b/usr/src/games/backgammon/tutor.h
new file mode 100644 (file)
index 0000000..7eaede3
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *     tutor.h 4.1     82/05/11
+ */
+
+struct situatn  {
+       int     brd[26];
+       int     roll1;
+       int     roll2;
+       int     mp[4];
+       int     mg[4];
+       int     new1;
+       int     new2;
+       char    *(*com[8]);
+};