home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
207.lha
/
BackGammon
/
back.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-27
|
12KB
|
441 lines
/********************************************************************/
/* */
/* Hoser BackGammon version 1.0 */
/* */
/* Robert Pfister */
/* */
/* Rfd#3 Box 2340 home:(207)-873-3520 */
/* Waterville, Maine 04901 */
/* */
/* Pfister_rob%dneast@dec.decwrl */
/* */
/* */
/* Copyright June,1987 */
/* */
/* This program will play a game of backgammon at the novice level */
/* */
/* The code is in 4 parts... */
/* / */
/* \/ 1) back.c - main driver */
/* 2) eval.c - evaluation of moves */
/* 3) backscn.c - screen stuff.. */
/* 4) backmenu.c - menu stuff, help text, and ``decoder'' */
/* */
/* this was compiled under Manx 3.20a, using long integers */
/* */
/********************************************************************/
#include <libraries/dos.h>
extern int AvgPos;
extern int Moves;
int MeInc,YouInc=0;
int MeD,MeM,YouD,YouM=0;
int MeBar,YouBar=0;
int Me2,You2=0;
#define StackSize 500
static int BoardPos[StackSize][26]; /* stack of the previous positions */
static int DicePos[StackSize][4]; /* stack of the dice rolls */
static int StackPos=0; /* how many moves back are we at? */
static int MoveList[4]; /* stack of this turns moves */
static int CurMove=0; /* place in the list */
int Uside; /* user side */
int Cside; /* computer side */
int Turn; /* whose turn is it? */
int board[26]; /* describes the board position..0 is the bar */
int Dice[4]; /* describes the 2->4 dice availible */
main() /* main procedure */
{
int i,j,play;
Gsetup();
Turn=setup(board,Dice);
for (;;) /* go until game is over */
{
if (Turn==Uside) DoMenuStrip("Your Turn");
else DoMenuStrip("My Turn");
ShowDice(Dice,Turn);
if (Turn==Uside)
{
/* store this board position */
StoreMove();
/* user stats */
if (Dice[2]>0) You2++;
YouD+=Dice[0]+Dice[1]+Dice[2]+Dice[3];
YouM++;
if (board[25]<0) YouBar++;
/* do the Move */
do
if (UserMove(board,Dice,Turn)==0) GameOver(); /* escape */
while ( (Turn==Uside)&&
(Won(board,Turn)==0)&&
(Dice[0]+Dice[1]+Dice[2]+Dice[3]!=0) );
}
else /* turn==Cside */
{
/* computer stats */
if (Dice[2]>0) Me2++;
MeD+=Dice[0]+Dice[1]+Dice[2]+Dice[3];
MeM++;
if (board[0]>0) MeBar++;
/* do move */
GenerateMoves(board,Dice);
DoMove(board);
}
Turn=Turn*-1;
Roll(Dice);
/* signal to restart the game */
if (Turn==0) Turn=setup(board,Dice);
/* did user win yet? */
if (Won(board,Uside))
{
stats();
if (requestor("I lose Play Again?","No","Yes")) GameOver();
else Turn=setup(board,Dice);
}
/* did computer win yet? */
if (Won(board,Cside))
{
stats();
if (requestor("Heehee. I Win. Play Again?","No","Yes")) GameOver();
else Turn=setup(board,Dice);
}
ShowDice(Dice,Turn);
} /* end do forever */
} /* end of main */
Restart()
{
Turn=0;
}
StoreMove()
{
int i;
if (StackPos<StackSize+1) /* can only store that many */
{
for (i=0;i<26;i++)
BoardPos[StackPos][i]=board[i];
for (i=0;i<4;i++)
DicePos[StackPos][i]=Dice[i];
StackPos++;
}
/* printf("STORE: stack is at %d \n",StackPos); */
}
RecallMove(how)
int how;
{
int i;
StackPos=StackPos-1+how;
if (StackPos<0) StackPos=0;
for (i=0;i<26;i++)
if (board[i]!=BoardPos[StackPos][i])
{ /* only refresh stuff changed */
board[i]=BoardPos[StackPos][i];
PutSpike(i,board[i]);
}
for (i=0;i<4;i++)
Dice[i]=DicePos[StackPos][i];
ShowDice(Dice,Uside);
StackPos++;
/* printf("RECALL: stack is at %d \n",StackPos); */
}
Won(board,side)
int board[26],side;
{
int i;
if (side==1) for(i=0;((board[i]<=0)&&(i<=25));i++);
else for(i=0;((board[i]>=0)&&(i<=25));i++);
if (i==26) return(1);
else return(0);
}
UserMove(board,Dice,side)
int board[26],Dice[4],side;
{
char Action;
int Pick,Valid; /* flags */
int i,x,y;
Valid=0;
Pick =0;
while (Valid==0)
{
Action=Whats_up(&x);
UnDoMenuStrip();
switch (Action)
{
/* check for abortion */
case 'D':Dice[0]=0;
Dice[1]=0;
Dice[2]=0;
Dice[3]=0;
Valid=1;
YouInc++;
break;
case 'Q':
Valid=-1;
break;
case 'P':if (Pick==0)
{
if (board[x]*side<=0)
DoMenuStrip("No peice there!!");
else
{
Pick=1;
y=x;
}
break;
}
else if (Pick==1) /* only if peice marked already */
{
Pick =0;
for (i=0;(Valid==0)&&(i<4);i++)
{
if ((valid(board,y,x,Dice[i]))&&(Dice[i]!=0))
{
BlinkPeice(board,y);
update(board,y,x,side);
PutSpike(y ,board[ y]);
BlinkPeice(board,x);
PutSpike(0 ,board[ 0]);
PutSpike(25,board[25]);
Valid=1;
Dice[i]=0;
}
} /* end for */
if (Valid==0) DoMenuStrip("Not Valid move");
break;
} /* end if...case 'M' */
case 'C':Valid=DoMenu(x);
break;
default :break;
} /* end of case */
} /* end while Valid==0 */
if (Valid==-1) return(0);
return(1);
} /* end UserMove */
Roll(d) /* roll the dice (4 results) */
int d[4];
{
long i,k,num1,num2;
struct DateStamp time;
DateStamp(&time);
k=time.ds_Tick;
for (i=1;i<=k;i++)
{
num1=RangeRand(6L)+1;
num2=RangeRand(6L)+1;
}
d[0]=num1;
d[1]=num2;
if (num1==num2) /* if rolled doubles */
{
d[2]=num1;
d[3]=num2;
}
else
{
d[2]=0;
d[3]=0;
}
if (d[3]==0) return(0);
else return(1);
}
GameOver()
{
stats();
finit();
exit(0);
}
stats()
{
if ((YouM!=0)&&(MeM!=0))
{
printf("Statistics on the Game \n");
printf("-------------------------------------------------------\n");
printf("number of moves %ld avg positions evaluated %ld \n",MeM,AvgPos/MeM);
printf("\n");
printf("avg roll : User %ld Computer %ld \n",YouD/YouM,MeD/MeM);
printf("doubles : User %ld Computer %ld \n",You2,Me2);
printf("inc. Moves : User %ld Computer %ld \n",YouInc,MeInc);
printf("Turns on bar: User %ld Computer %ld \n",YouBar,MeBar);
printf("-------------------------------------------------------\n");
}
MeM=0; YouD=0; YouM=0; MeD=0;
AvgPos=0; You2=0; Me2=0; YouInc=0; MeInc=0;
YouBar=0; MeBar=0;
}
setup(board,Dice)
int board[26],Dice[4];
{
int i;
Uside=-1;
Cside= 1;
/* set the board to the initial setting */
for (i=0; i<=25; i++)
{
board[i]= 0;
}
board[ 1]= 2;
board[ 6]=-5;
board[ 8]=-3;
board[12]= 5;
board[13]=-5;
board[17]= 3;
board[19]= 5;
board[24]=-2;
for (i=0;i<=25;i++)
{
PutSpike(i,board[i]);
}
/* see who goes first */
while (Roll(Dice)); /* until no doubles */
if (Dice[0]>Dice[1])
return(Uside);
else return(Cside);
}
/* is the move valid for the board, and one die */
valid(board,m1,m2,p) /* board, start, stop, dice roll */
int board[26];
int m1,m2,p;
{
int sign,i,All_In,bar;
All_In=-1;
/* what direction are we going? */
if (board[m1]>0)
{
sign=Cside;
if (Cside==1) bar=0;
else bar=25;
/* is there a man on the bar?? */
if ((board[bar]!=0)&&(m1!=0)) return(0);
/* see if all peices are in home base */
for(i=0;(i<=24)&&(All_In==-1);i++)
if (board[i]>0) All_In=i;
/* check if can take it off */
if (m2>24)
{
if ((All_In>18)&&
( (m1==(25-p)) || ((25-p)<All_In)&&(m1==All_In) )) return(1);
else return(0);
}
}
else
{
sign=-1;
/* is there a man on the bar? */
if ((board[25]!=0)&&(m1!=25)) return(0);
/* see if all peices are in home base */
for(i=25;(i>=1)&&(All_In==-1);i--)
if (board[i]<0) All_In=i;
/* see if can take off */
if (m2==m1)
{
if ((All_In<7)&&
( (m1==p)|| ((p>All_In)&&(m1==All_In) ))) return(1);
else return(0);
}
}
/* does dice roll make sense for the move picked? */
if ((m2-m1)!=(p*sign)) return(0);
/* if spike has more than 1 opponent */
if (board[m2] * sign < -1) return(0);
/* I suppose that's all there is..*/
return(1);
}
/* put a given move onto the board */
update(board,m1,m2,sign)
int board[26],m1,m2,sign;
{
int bar;
if (sign>0) bar=0;
else bar=25;
/* remove the peice from the 'source' spike */
board[m1]=board[m1]-sign;
/* if taking a peice off, dont go any furthur */
if ((m2==m1)||(m2>=25)) return(1);
/* add a peice to the 'destination' spike, consider if capturing*/
board[m2]=board[m2]+sign;
if (board[m2]==0) {
board[m2 ]=sign;
board[25-bar]=board[25-bar]-sign;
}
return(0);
}