/********************************************************************/ /* */ /* 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 all rights reserved. */ /* */ /* 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 */ /* */ /********************************************************************/ /****************************************************************/ /* These routines do all the thinking for the computer side */ /* */ /* (read: the magic lives here) */ /****************************************************************/ #define Running 1 #define Blocking 2 #define Pegging 3 #define BackGame 4 extern int MeInc; int Moves =0; int AvgPos=0; int LastVun=0; int list[4][2]; int count=0; int max=0; int GameStat=0; int MaxStat=0; int block[26]={-1,1,2,3,4,5,6, 8,9,10,11,12,13 ,14,15,17,21,25,27, 25,21,19,8,3,1,0}; int run[26] ={-1,1,2,3,4,5,6, 15,16,17,18,19,20, 30,31,32,33,34,35, 50,51,52,53,54,55}; int peg[26] ={-20,0,0,0,0,0,0 ,1,2,3,4,5,6, 30,31,32,33,34,35, 50,49,48,47,46,45,0}; int back[26]={20,40,30,20,10,5,0 ,1,2,3,4,5,6, 30,31,32,30,40,50, 50,49,48,30,20,10,0}; Eval(Board) int Board[26]; { register int i; int num,value,me,you; int Msum,Ysum; num=0; value=0; /* see who is ahead */ Msum=0; for(i=0;i<=24;i++) if (Board[i]>0) Msum+=(25-i)*Board[i]; Ysum=0; for(i=1;i<=25;i++) if (Board[i]<0) Ysum-=i*Board[i]; for (i= 0;(i<=24)&&(Board[i]<=0);i++); /* first occurance of me */ me=i; for (i=25;(i>=1)&&(Board[i]>=0);i--);/* first occurance of you */ you=1; GameStat=BackGame; /* default case */ if (Ysum>Msum+10) GameStat=Running; /* if closer to winning than them */ if (you>18) GameStat=Blocking; /* if a opponent is within the bounds */ if (me>you) GameStat=Pegging; /* if complete separation */ for(i=0;i<=24;i++) { if (Board[i]>0) { num=num+Board[i]; switch(GameStat) { case BackGame: value+=back[i]*Board[i]; if (i<18) value+=3*vunerable(Board,i); break; case Pegging: value+=peg[i]*Board[i]; break; case Blocking: value+=block[i]*Board[i]; value-=4*vunerable(Board,i); value-=6*doom(Board); break; case Running: value+=run[i]*Board[i]; value-=6*vunerable(Board,i); value-=6*doom(Board); break; } } } /* add points for taking men off...more if no chance of being taken */ if (GameStat==Pegging) value+=(15-num)*300; else value+=(15-num)*75; /* if blocking game, check the block length...add points for more */ switch(GameStat) { case BackGame: num=0; for(i=0;i<=6;i++) if ((Board[i]>0)&&(you>i)) num++; value+=100*num; num=0; for(i=15;i<=21;i++) if (Board[i]>0) num+=Board[i]; value+=30*num; value-=100*Board[25]; num=0; for(i=17;i<=23;i++) if (Board[i]>=2) num++; value+=(num*300); break; case Blocking: num=0; for(i=14;i<=22;i++) { if (Board[i]>=2) num++; if ((you>i)&&(Board[i]>=2)) num++; } value+=(num*400); num=0; for(i=0;i<=17;i++) if (Board[i]>0) num+=(Board[i]*(18-i)*(18-i)); value-=num/1.5; break; case Pegging: case Running: num=0; for(i=0;i<=17;i++) if (Board[i]>0) num++; value-=10*num; num=0; for(i=0;i<=17;i++) if (Board[i]>0) num+=(Board[i]*(26-i)*(26-i)); value-=num; break; } return(value); } vunerable(Board,pos) int Board[26],pos; { register int i,j,k; int value; int HitTable[7][7]; value=0; if ( (Board[pos]<0) || (pos==0) || (Board[pos]>=2) ) return (value); /* intitialize table */ for(i=1;i<=6;i++) for(j=1;j<=6;j++) HitTable[i][j]=0; /* look at all dice within 12 places */ for(i=1;i<=12;i++) { if (pos-i>=0) /* within the board */ if (Board[pos-i]<0) /* there peice exists at that place */ if (valid(Board,pos,pos-i,i)) /* can capture legally */ { /*--------------------------------------------------*/ /* find hits for one die */ if (i<=6) for(j=1;j<=6;j++) { HitTable[i][j]=1; HitTable[j][i]=1; } /* figure out combinations */ for (j=1;jmax)) { max=j; MaxStat=GameStat; list[0][0]=i1; list[0][1]=i1+Dice[0]; list[1][0]=i2; list[1][1]=i2+Dice[1]; list[2][0]=i3; list[2][1]=i3+Dice[2]; list[3][0]=i4; list[3][1]=i4+Dice[3]; } } GenerateMoves(Board,Dice) int Board[26],Dice[4]; { register int i; int Dice2[4]; count=0; PutMoveNumber(count); /* check for doubles rolled */ if (Dice[2]!=0) { Find4(Board,Dice); if (count!=0) return(0); MeInc++; Find3(Board,Dice); if (count!=0) return(0); Find2(Board,Dice); if (count!=0) return(0); } else { Find2(Board,Dice); Dice2[0]=Dice[1]; Dice2[1]=Dice[0]; Dice2[2]=Dice[2]; Dice2[3]=Dice[3]; Find2(Board,Dice2); if (count!=0) return(0); MeInc++; } Find1(Board,Dice); return(0); } /* end of generate */ Find4(Board,Dice) int Board[26],Dice[4]; { register int i1,i2,i3,i4; int Board1[26],Board2[26],Board3[26],Board4[26]; for (i1=0;i1<=24;i1++) { if (Board[i1]>0) if (valid(Board,i1,i1+Dice[0],Dice[0])) { CopyBoard(Board,Board1); update(Board1,i1,i1+Dice[0],1); for (i2=0;i2<=24;i2++) { if (Board1[i2]>0) if (valid(Board1,i2,i2+Dice[1],Dice[1])) { CopyBoard(Board1,Board2); update(Board2,i2,i2+Dice[1],1); for (i3=0;i3<=24;i3++) { if (Board2[i3]>0) if (valid(Board2,i3,i3+Dice[2],Dice[2])) { CopyBoard(Board2,Board3); update(Board3,i3,i3+Dice[2],1); for (i4=0;i4<=24;i4++) { if (Board3[i4]>0) if (valid(Board3,i4,i4+Dice[3],Dice[3])) { count++; CopyBoard(Board3,Board4); update(Board4,i4,i4+Dice[3],1); FindMove(Board4,Dice,i1,i2,i3,i4); } } /* end for i4 */ } /* end valid Dice[2] */ } /* end for i3 */ } /* end valid Dice[1] */ } /* end for i2 */ } /* end if Valid Dice[0] */ } /* end for i1 */ return(0); } /* end of Find4 */ Find3(Board,Dice) int Board[26],Dice[4]; { register int i1,i2,i3; int Board1[26],Board2[26],Board3[26]; for (i1=0;i1<=24;i1++) { if (Board[i1]>0) if (valid(Board,i1,i1+Dice[0],Dice[0])) { CopyBoard(Board,Board1); update(Board1,i1,i1+Dice[0],1); for (i2=0;i2<=24;i2++) { if (Board1[i2]>0) if (valid(Board1,i2,i2+Dice[1],Dice[1])) { CopyBoard(Board1,Board2); update(Board2,i2,i2+Dice[1],1); for (i3=0;i3<=24;i3++) { if (Board2[i3]>0) if (valid(Board2,i3,i3+Dice[2],Dice[2])) { count++; CopyBoard(Board2,Board3); update(Board3,i3,i3+Dice[2],1); FindMove(Board3,Dice,i1,i2,i3,-1); } /* end valid Dice[2] */ } /* end for i3 */ } /* end valid Dice[1] */ } /* end for i2 */ } /* end if Valid Dice[0] */ } /* end for i1 */ return(0); } /* end of Find3 */ Find2(Board,Dice) int Board[26],Dice[4]; { register int i1,i2; int Board1[26],Board2[26]; for (i1=0;i1<=24;i1++) { if (Board[i1]>0) if (valid(Board,i1,i1+Dice[0],Dice[0])) { CopyBoard(Board,Board1); update(Board1,i1,i1+Dice[0],1); for (i2=0;i2<=24;i2++) { if (Board1[i2]>0) if (valid(Board1,i2,i2+Dice[1],Dice[1])) { count++; CopyBoard(Board1,Board2); update(Board2,i2,i2+Dice[1],1); FindMove(Board2,Dice,i1,i2,-1,-1); }/* end valid Dice[1] */ }/* end for i2 */ }/* end if Valid Dice[0] */ }/* end for i1 */ }/* end find2 */ Find1(Board,Dice) int Board[26],Dice[4]; { register int i1,i2; int Board1[26],Dice2[4]; for (i2=0;i2<=1;i2++) { Dice2[0]=Dice[i2]; Dice2[1]=0; Dice2[2]=0; Dice2[3]=0; for (i1=0;i1<=24;i1++) if (Board[i1]>0) if (valid(Board,i1,i1+Dice[i2],Dice[i2])) { count++; CopyBoard(Board,Board1); update(Board1,i1,i1+Dice[i2],1); FindMove(Board1,Dice2,i1,-1,-1,-1); } } return(0); } /* end of find1 */