/********************************************************************/ /* */ /* 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 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=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)=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); }