static char sccsid
[] = "@(#)btlgammon.c 1.2 (Berkeley) %G%";
** The game of Backgammon
#define RULES "/usr/games/lib/backrules"
char level
; /*'b'=beginner, 'i'=intermediate, 'e'=expert*/
int brown
[] = { /* brown position table */
0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
int white
[] = { /* white position table */
0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
0, 11, 12, 13, 14, 15, 16,
int k
, n
, pid
, ret
, rpid
, t
;
fprintf(stdout
, "Instructions? ");
fprintf(stdout
, "Opponent's level: b - beginner,\n");
fprintf(stdout
, "i - intermediate, e - expert? ");
fprintf(stdout
, "You will play brown.\n\n");
fprintf(stdout
, "Would you like to roll your own dice? ");
fprintf(stdout
, "Would you like to go first? ");
fprintf(stdout
, "white rolls %d, %d\n", die1
, die2
);
fprintf(stdout
, "white's move is:");
if(nextmove(white
, brown
) == NIL
)
if(piececount(white
, 0, 24) == 0){
fprintf(stdout
, "White wins");
if(piececount(brown
, 0, 6) != 0)
fprintf(stdout
, " with a Backgammon!\n");
else if (piececount(brown
, 0, 24) == 24)
fprintf(stdout
, " with a Gammon.\n");
fprintf(stdout
, "\nYour roll is %d %d\n", die1
, die2
);
fprintf(stdout
, "Move? ");
case '\0': /* empty line */
fprintf(stdout
, "Brown's move skipped.\n");
case 'b': /* how many beared off? */
fprintf(stdout
, "Brown: %d\n", piececount(brown
, 0, 24) - 15);
fprintf(stdout
, "White: %d\n", piececount(white
, 0, 24) - 15);
case 'p': /* print board */
case 's': /* stop auto printing of board */
case 'r': /* resume auto printing */
case 'm': /* print possible moves */
case 'q': /* i give up */
case '!': /* escape to Shell */
#ifdef ADD_A_MAJOR_SECURITY_HOLE
if (!(pid
= vfork()) == 0) {
execl("/bin/sh", "sh", "-", 0);
fprintf(stderr
, "back: cannot exec /bin/sh!\n");
while((rpid
= wait(&ret
)) != pid
&& rpid
!= -1)
case '?': /* well, what can i do? */
fprintf(stdout
, "<newline> skip this move\n");
fprintf(stdout
, "b number beared off\n");
fprintf(stdout
, "p print board\n");
fprintf(stdout
, "q quit\n");
fprintf(stdout
, "r resume auto print of board\n");
fprintf(stdout
, "s stop auto print of board\n");
fprintf(stdout
, "! escape to Shell\n");
n
= sscanf(s
,"%d%d%d%d%d",&go
[0],&go
[1],&go
[2],&go
[3],&go
[4]);
if((die1
!= die2
&& n
> 2) || n
> 4){
fprintf(stdout
, "Too many moves.\n");
if(0 <= go
[k
] && go
[k
] <= 24)
fprintf(stdout
, "Move %d illegal.\n", go
[k
]);
if(play(brown
, white
, go
))
if(piececount(brown
, 0, 24) == 0){
fprintf(stdout
, "Brown wins");
if(piececount(white
, 0, 6) != 0)
fprintf(stdout
, " with a Backgammon.\n");
else if(piececount(white
, 0, 24) == 24)
fprintf(stdout
, " with a gammon.\n");
int *player
,*playee
,pos
[];
for(k
=0; k
< player
[0]; k
++){ /*blots on player[0] must be moved first*/
fprintf(stdout
, "Stone on bar must be moved first.\n");
for(k
= 0; (ipos
=pos
[k
]) != NIL
; k
++){
if(n
> 0 && playee
[n
] >= 2)
if(piececount(player
,0,18) != 0)
if((ipos
+die
) != 25 && piececount(player
,19,24-die
)!=0)
for(k
= 0; pos
[k
] != NIL
; k
++){
fprintf(stdout
, "Move %d illegal.\n", ipos
);
fprintf(stdout
, "no move possible.\n");
k
=strategy(player
,playee
); /*select kth possible move*/
fprintf(stdout
, "No move possible\n");
else for(n
= 0; n
< 4; n
++){
if(moves
[k
].pos
[n
] == NIL
)
fprintf(stdout
, " %d, %d",25-moves
[k
].pos
[n
],moves
[k
].mov
[n
]);
if(moves
[k
].pos
[n
] == NIL
)
player
[moves
[k
].pos
[n
]]--;
player
[moves
[k
].pos
[n
]+moves
[k
].mov
[n
]]++;
t
=25-moves
[k
].pos
[n
]-moves
[k
].mov
[n
];
piececount(player
,startrow
,endrow
)
int *player
,startrow
,endrow
;
while(startrow
<= endrow
)
sum
+= player
[startrow
++];
fprintf(stdout
, "Possible moves are:\n");
for(i1
= 0; i1
< imoves
; i1
++){
fprintf(stdout
, "\n%d",i1
);
for (i2
= 0; i2
<4; i2
++){
if(moves
[i1
].pos
[i2
] == NIL
)
fprintf(stdout
, "%d, %d",moves
[i1
].pos
[i2
],moves
[i1
].mov
[i2
]);
if(who
== BROWN
&& nobroll
) {
fprintf(stdout
, "Roll? ");
n
= sscanf(s
, "%d%d", &die1
, &die2
);
if(n
!= 2 || die1
< 1 || die1
> 6 || die2
< 1 || die2
> 6)
fprintf(stdout
, "Illegal - I'll do it!\n");
die1
= ((rand()>>8) % 6) + 1;
die2
= ((rand()>>8) % 6) + 1;
for(i
= 0; i
<= 24; i
++){
if((k
=25-i
-die1
) > 0 && movee
[k
] >= 2)
if(piececount(mover
, 0, 18) != 0)
if((i
+die1
) != 25 && piececount(mover
,19,i
-1) != 0)
for(j
= 0; j
<= 24; j
++){
if((k
=25-j
-die2
) > 0 && movee
[k
] >= 2)
if(piececount(mover
,0,18) != 0)
if((j
+die2
) != 25 && piececount(mover
,19,j
-1) != 0)
for(l
= 0; l
<= 24; l
++){
if((k
=25-l
-die1
) > 0 && movee
[k
] >= 2)
if(piececount(mover
, 0, 18) != 0)
if((l
+die2
) != 25 && piececount(mover
,19,l
-1) != 0)
if((k
=25-m
-die1
) >= 0 && movee
[k
] >= 2)
if(piececount(mover
,0,18) != 0)
if((m
+die2
) != 25 && piececount(mover
,19,m
-1) != 0)
moves
[imoves
].pos
[t
] = NIL
;
moves
[imoves
].mov
[3]=die1
;
moves
[imoves
].mov
[2]=die1
;
moves
[imoves
].mov
[1]=die2
;
moves
[imoves
].mov
[0]=die1
;
int k
, n
, nn
, bestval
, moveval
, prob
;
for(k
= 0; k
< imoves
; k
++){
if((moveval
=eval(player
,playee
,k
,&prob
)) < bestval
)
if((moveval
=probmoves
[k
]) > prob
)
goodmoves
[n
]=goodmoves
[k
];
probmoves
[n
++]=probmoves
[k
];
return(goodmoves
[(rand()>>4)%n
]);
eval(player
,playee
,k
,prob
)
int *player
,*playee
,k
,*prob
;
int newtry
[31], newother
[31], *r
, *q
, *p
, n
, sum
, first
;
int ii
, lastwhite
, lastbrown
;
for(p
= newtry
+25; p
< q
; p
++) /* zero out spaces for hit pieces */
if(moves
[k
].pos
[n
] == NIL
)
newtry
[moves
[k
].pos
[n
]]--;
newtry
[ii
=moves
[k
].pos
[n
]+moves
[k
].mov
[n
]]++;
if(ii
<25 && newother
[25-ii
]==1){
if(ii
<=15 && level
=='e') /* hit if near other's home */
for(lastbrown
= 0; newother
[lastbrown
] == 0; lastbrown
++);
for(lastwhite
= 0; newtry
[lastwhite
] == 0; lastwhite
++)
lastwhite
= 25-lastwhite
;
if(lastwhite
<=6 && lastwhite
<lastbrown
)
/* experts running game. */
/* first priority is to */
/* get all pieces into */
if(lastwhite
<lastbrown
&& level
=='e' && lastwhite
>6) {
for(sum
= 1000; lastwhite
> 6; lastwhite
--)
sum
= sum
-lastwhite
*newtry
[25-lastwhite
];
for(first
= 0; first
< 25; first
++)
if(newother
[first
] != 0) /*find other's first piece*/
for(p
= newtry
+1; p
< q
;) /* blocked points are good */
if(first
> 5) { /* only stress removing pieces if */
/* homeboard cannot be hit */
sum
+= *p
++ * n
; /*remove pieces, but just barely*/
r
= newtry
+25-first
; /*singles past this point can't be hit*/
for(p
= newtry
+7; p
< r
; )
if(*p
++ == 1) /*singles are bad after 1st 6 points if they can be hit*/
for(p
= newtry
; p
< q
; ) /*bad to be on 1st three points*/
*prob
+= n
*getprob(newtry
,newother
,6*n
-5,6*n
);
if((fd
= open(RULES
, 0)) < 0) {
fprintf(stderr
, "back: cannot open %s\n", RULES
);
while(r
= read(fd
, buf
, BUFSIZ
))
getprob(player
,playee
,start
,finish
)
int *player
,*playee
,start
,finish
;
{ /*returns the probability (times 102) that any
pieces belonging to 'player' and lying between
his points 'start' and 'finish' will be hit
by a piece belonging to playee
for(; start
<= finish
; start
++){
for(k
= 1; k
<= 12; k
++){
static char undersc
[]="______________________________________________________";
fprintf(stdout
, "White's Home\n%s\r",undersc
);
fprintf(stdout
, "%4d",k
);
fprintf(stdout
, "%4d",k
);
numline(brown
, white
, 1, 6);
numline(brown
, white
, 7, 12);
colorline(brown
, 'B', white
, 'W', 1, 6);
colorline(brown
, 'B', white
, 'W', 7, 12);
fprintf(stdout
, "%28dW\n",white
[0]);
fprintf(stdout
, "%28dB\n", brown
[0]);
colorline(white
, 'W', brown
, 'B', 1, 6);
colorline(white
, 'W', brown
, 'B', 7, 12);
fprintf(stdout
, "\n%s\r",undersc
);
numline(white
, brown
, 1, 6);
numline(white
, brown
, 7, 12);
for(k
= 24; k
>= 19; k
--)
fprintf(stdout
, "%4d",k
);
for(k
= 18; k
>= 13; k
--)
fprintf(stdout
, "%4d",k
);
fprintf(stdout
, "\nBrown's Home\n\n\n\n\n");
numline(upcol
,downcol
,start
,fin
)
int *upcol
,*downcol
,start
,fin
;
for(k
= start
; k
<= fin
; k
++){
if((n
= upcol
[k
]) != 0 || (n
= downcol
[25-k
]) != 0)
fprintf(stdout
, "%4d", n
);
colorline(upcol
,c1
,downcol
,c2
,start
,fin
)
int *upcol
,*downcol
,start
,fin
;
for(k
= start
; k
<= fin
; k
++){
fprintf(stdout
, " %c",c
);