home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************/
- /* */
- /* 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;j<i;j++)
- {
- /* first die is j, second is k */
- k=i-j;
-
- /* check legality of the intermediate place */
-
- if (valid (Board,pos,pos-j,j))
- {
- HitTable[k][j]=1;
- HitTable[j][k]=1;
- }
-
- if (valid (Board,pos,pos-k,k))
- {
- HitTable[k][j]=1;
- HitTable[j][k]=1;
- }
- }
- /*---------------------------------------------------*/
- } /* end of valid (board,position) */
-
- } /* end of for i */
-
- /* find how many hits in that table */
- for(i=1;i<=6;i++)
- for(j=1;j<=6;j++)
- if (HitTable[i][j]==1) value++;
-
- LastVun=value;
-
- return(value);
-
- } /* end of vunerable */
-
-
- doom(Board)
- int Board[26];
- {
- register int i,value;
-
- if (LastVun==0) return(0);
-
- /* find the "doom" factor..the possibilty of getting outa being captured */
- for(i=1;i<=10;i++) if (Board[i]<-1) value+=5;
-
- return(value);
- }
-
- /* copy b1 to b2 */
- CopyBoard(b1,b2)
- int b1[26],b2[26];
- {
- register int i;
- for (i=0;i<=25;i++)
- {
- b2[i]=b1[i];
- } /* end for */
- } /* end of Copy */
-
- DoMove(Board)
- int Board[26];
- {
- int j,sum;
-
- AvgPos+=count;
-
- /* dont do anything if nothing to be done */
- if (count==0)
- {
- DoMenuStrip("Cant move from this position!!");
- return(0);
- }
-
- PutMoveNumber(count);
-
- /* show move */
- for(j=0;j<=3;j++)
- if (list[j][0]!=-1)
- {
- BlinkPeice(Board,list[j][0]);
- update(Board,list[j][0], list[j][1] ,1);
- PutSpike( list[j][0],Board[list[j][0]] );
- BlinkPeice(Board,list[j][1]);
- }
-
- /* touch up the bar's */
- PutSpike(0 ,Board[ 0]);
- PutSpike(25,Board[25]);
-
- }
-
- FindMove(Board,Dice,i1,i2,i3,i4)
- int Board[26],Dice[4],i1,i2,i3,i4;
- {
- int j;
-
- if ((count<50)||(10*(count/10)==count))
- PutMoveNumber(count);
- j=Eval(Board);
- if ((count==1)||(j>max))
- {
- 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 */
-