home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 207.lha / BackGammon / back.c < prev    next >
C/C++ Source or Header  |  1988-12-27  |  12KB  |  441 lines

  1. /********************************************************************/
  2. /*                                                                  */
  3. /*  Hoser BackGammon version 1.0                                    */
  4. /*                                                                  */
  5. /*      Robert Pfister                                              */
  6. /*                                                                  */
  7. /*      Rfd#3 Box 2340                home:(207)-873-3520           */
  8. /*      Waterville, Maine 04901                                     */
  9. /*                                                                  */
  10. /*      Pfister_rob%dneast@dec.decwrl                               */
  11. /*                                                                  */
  12. /*                                                                  */
  13. /*  Copyright  June,1987                                            */
  14. /*                                                                  */
  15. /*  This program will play a game of backgammon at the novice level */
  16. /*                                                                  */
  17. /*  The code is in 4 parts...                                       */
  18. /*   /                                                              */
  19. /* \/    1) back.c     - main driver                                */
  20. /*       2) eval.c     - evaluation of moves                        */
  21. /*       3) backscn.c  - screen stuff..                             */
  22. /*       4) backmenu.c - menu stuff, help text, and ``decoder''     */
  23. /*                                                                  */
  24. /* this was compiled under Manx 3.20a, using long integers          */
  25. /*                                                                  */
  26. /********************************************************************/
  27. #include <libraries/dos.h>
  28.  
  29. extern int AvgPos;
  30. extern int Moves;
  31.  
  32. int MeInc,YouInc=0;
  33. int MeD,MeM,YouD,YouM=0;
  34. int MeBar,YouBar=0;
  35. int Me2,You2=0;
  36.  
  37. #define StackSize 500
  38.   static int BoardPos[StackSize][26]; /* stack of the previous positions */
  39.   static int DicePos[StackSize][4];   /* stack of the dice rolls */
  40.  
  41.   static int StackPos=0;     /* how many moves back are we at? */
  42.  
  43.   static int MoveList[4];       /* stack of this turns moves */
  44.   static int CurMove=0;        /* place in the list */
  45.   
  46. int Uside;    /* user side */
  47. int Cside;    /* computer side */
  48.  
  49. int Turn;     /* whose turn is it? */
  50.  
  51.  int board[26];    /* describes the board position..0 is the bar */
  52.  int Dice[4];      /* describes the 2->4 dice availible */
  53.  
  54. main() /* main procedure */
  55.   {
  56.  
  57.   int i,j,play;
  58.  
  59.    Gsetup();
  60.    Turn=setup(board,Dice);
  61.  
  62.    for (;;)         /* go until game is over */
  63.      {
  64.       if (Turn==Uside) DoMenuStrip("Your Turn");
  65.                  else  DoMenuStrip("My Turn");
  66.  
  67.       ShowDice(Dice,Turn);
  68.       if (Turn==Uside)
  69.       {
  70.        /* store this board position */
  71.            StoreMove();
  72.        /* user stats */
  73.            if (Dice[2]>0) You2++;
  74.            YouD+=Dice[0]+Dice[1]+Dice[2]+Dice[3];
  75.            YouM++;
  76.            if (board[25]<0) YouBar++;
  77.  
  78.  
  79.        /* do the Move */
  80.           do
  81.             if (UserMove(board,Dice,Turn)==0) GameOver(); /* escape */
  82.             while (  (Turn==Uside)&&
  83.                      (Won(board,Turn)==0)&&
  84.                      (Dice[0]+Dice[1]+Dice[2]+Dice[3]!=0) );
  85.        }
  86.        else /* turn==Cside */
  87.        {  
  88.            /* computer stats */
  89.               if (Dice[2]>0) Me2++;
  90.               MeD+=Dice[0]+Dice[1]+Dice[2]+Dice[3];
  91.               MeM++;
  92.               if (board[0]>0) MeBar++;
  93.  
  94.            /* do move */
  95.               GenerateMoves(board,Dice);
  96.               DoMove(board);
  97.            }
  98.  
  99.       Turn=Turn*-1;
  100.       Roll(Dice);
  101.  
  102.        /* signal to restart the game */
  103.           if (Turn==0) Turn=setup(board,Dice);
  104.           
  105.        /* did user win yet? */
  106.           if (Won(board,Uside))
  107.              {
  108.              stats();
  109.              if (requestor("I lose Play Again?","No","Yes")) GameOver();
  110.                                                 else Turn=setup(board,Dice);
  111.              }
  112.  
  113.        /* did computer win yet? */
  114.           if (Won(board,Cside))
  115.              {
  116.               stats();
  117.               if (requestor("Heehee. I Win. Play Again?","No","Yes")) GameOver();
  118.                                          else Turn=setup(board,Dice);
  119.              }
  120.       ShowDice(Dice,Turn);
  121.  
  122.     } /* end do forever */
  123.  
  124.  } /* end of main */
  125.  
  126. Restart()
  127. {
  128.  Turn=0;
  129. }
  130.  
  131. StoreMove()
  132.  int i;
  133.  
  134.  if (StackPos<StackSize+1) /* can only store that many */
  135.   {
  136.    for (i=0;i<26;i++)
  137.        BoardPos[StackPos][i]=board[i];       
  138.    for (i=0;i<4;i++)
  139.        DicePos[StackPos][i]=Dice[i];
  140.    StackPos++;
  141.    }
  142. /* printf("STORE: stack is at %d \n",StackPos); */
  143. }
  144.  
  145. RecallMove(how)
  146. int how;
  147. {
  148.   int i;
  149.  
  150.   StackPos=StackPos-1+how;
  151.   if (StackPos<0) StackPos=0;
  152.  
  153.   for (i=0;i<26;i++)
  154.       if (board[i]!=BoardPos[StackPos][i])
  155.          { /* only refresh stuff changed */
  156.           board[i]=BoardPos[StackPos][i];       
  157.           PutSpike(i,board[i]);
  158.         }
  159.  
  160.   for (i=0;i<4;i++)
  161.       Dice[i]=DicePos[StackPos][i];
  162.  
  163.   ShowDice(Dice,Uside);
  164.  StackPos++;
  165. /* printf("RECALL: stack is at %d \n",StackPos);  */
  166. }
  167.  
  168. Won(board,side)
  169.   int board[26],side;
  170.       {
  171.        int i;
  172.  
  173.        if (side==1) for(i=0;((board[i]<=0)&&(i<=25));i++);
  174.                else for(i=0;((board[i]>=0)&&(i<=25));i++);
  175.  
  176.        if (i==26) return(1);
  177.              else return(0);
  178.        }
  179.  
  180. UserMove(board,Dice,side)
  181.  int board[26],Dice[4],side;
  182.  {
  183.  char Action;
  184.  int  Pick,Valid;  /* flags */
  185.  int i,x,y;
  186.  
  187.  Valid=0;
  188.  Pick =0;
  189.  while (Valid==0)
  190.  {
  191.    Action=Whats_up(&x);
  192.    UnDoMenuStrip();
  193.    switch (Action)
  194.       {
  195.        /* check for abortion */
  196.        case 'D':Dice[0]=0;
  197.                 Dice[1]=0;
  198.                 Dice[2]=0;
  199.                 Dice[3]=0;
  200.                 Valid=1;
  201.                 YouInc++;
  202.                 break;
  203.  
  204.  
  205.        case 'Q':
  206.                 Valid=-1;
  207.                 break;
  208.  
  209.        case 'P':if (Pick==0)
  210.                    {
  211.                     if (board[x]*side<=0)
  212.                          DoMenuStrip("No peice there!!");
  213.                          else
  214.                              {
  215.                               Pick=1;
  216.                               y=x;
  217.                               }
  218.                           break;
  219.                      }
  220.  
  221.                      else if (Pick==1) /* only if peice marked already */
  222.                        {
  223.                          Pick =0;
  224.                          for (i=0;(Valid==0)&&(i<4);i++)
  225.                            {
  226.                              if ((valid(board,y,x,Dice[i]))&&(Dice[i]!=0))
  227.                                  {
  228.                                   BlinkPeice(board,y);
  229.                                   update(board,y,x,side);
  230.                                   PutSpike(y ,board[ y]);
  231.                                   BlinkPeice(board,x);
  232.                                   PutSpike(0 ,board[ 0]);
  233.                                   PutSpike(25,board[25]);
  234.                                   Valid=1;
  235.                                   Dice[i]=0;
  236.                                   }
  237.                              } /* end for */
  238.  
  239.                         if (Valid==0) DoMenuStrip("Not Valid move");
  240.  
  241.                           break;
  242.                          } /* end if...case 'M' */
  243.  
  244.             case 'C':Valid=DoMenu(x);
  245.                      break;
  246.                     
  247.             default :break;
  248.  
  249.             } /* end of case */
  250.  
  251.       } /* end while Valid==0 */
  252.  
  253.    if (Valid==-1) return(0);
  254.    return(1);
  255.    } /* end UserMove */
  256.  
  257.  
  258. Roll(d)     /* roll the dice  (4 results) */
  259. int  d[4];
  260.   {
  261.   long  i,k,num1,num2;
  262.   struct DateStamp time;
  263.  
  264.   DateStamp(&time);
  265.  
  266.   k=time.ds_Tick;
  267.   
  268.   for (i=1;i<=k;i++)
  269.     {
  270.       num1=RangeRand(6L)+1;
  271.       num2=RangeRand(6L)+1;
  272.      }
  273.   d[0]=num1;
  274.   d[1]=num2;
  275.   if (num1==num2)   /* if rolled doubles */
  276.          {
  277.           d[2]=num1;
  278.           d[3]=num2;
  279.          }
  280.          else
  281.          {
  282.           d[2]=0;
  283.           d[3]=0;
  284.          }
  285.   if (d[3]==0) return(0);
  286.           else return(1);
  287.   }
  288.  
  289. GameOver()
  290. {
  291.  stats();
  292.  finit();
  293.  exit(0);
  294.  }
  295.  
  296. stats()
  297.    {
  298.     if ((YouM!=0)&&(MeM!=0))
  299.        {
  300.         printf("Statistics on the Game \n");
  301.         printf("-------------------------------------------------------\n");
  302.         printf("number of moves %ld  avg positions evaluated %ld \n",MeM,AvgPos/MeM);
  303.         printf("\n");
  304.         printf("avg roll    : User %ld Computer %ld \n",YouD/YouM,MeD/MeM);
  305.         printf("doubles     : User %ld Computer %ld \n",You2,Me2);
  306.         printf("inc. Moves  : User %ld Computer %ld \n",YouInc,MeInc);
  307.         printf("Turns on bar: User %ld Computer %ld \n",YouBar,MeBar);
  308.         printf("-------------------------------------------------------\n");
  309.         }
  310.      MeM=0;     YouD=0; YouM=0;  MeD=0;
  311.      AvgPos=0;  You2=0;  Me2=0;  YouInc=0; MeInc=0;
  312.      YouBar=0; MeBar=0;
  313.    }
  314.  
  315. setup(board,Dice)
  316. int board[26],Dice[4];
  317.  {
  318.  int i;
  319.  
  320.  Uside=-1;
  321.  Cside= 1;
  322.  
  323.  /* set the board to the initial setting */
  324.  
  325.   for (i=0; i<=25; i++)
  326.      {
  327.       board[i]= 0;
  328.       }
  329.  
  330.   board[ 1]= 2;
  331.   board[ 6]=-5;
  332.   board[ 8]=-3;
  333.   board[12]= 5;
  334.   board[13]=-5;
  335.   board[17]= 3;
  336.   board[19]= 5;
  337.   board[24]=-2;
  338.   for (i=0;i<=25;i++)
  339.       {
  340.        PutSpike(i,board[i]);
  341.        }
  342.  
  343.  /* see who goes first */
  344.  
  345.  while (Roll(Dice));  /* until no doubles */
  346.  
  347.  if (Dice[0]>Dice[1])
  348.            return(Uside);
  349.       else return(Cside);
  350.   }
  351.  
  352. /* is the move valid for the board, and one die */
  353. valid(board,m1,m2,p)  /* board, start, stop, dice roll */
  354. int board[26];
  355. int m1,m2,p;
  356.   {
  357.   int sign,i,All_In,bar;
  358.  
  359.      
  360.   All_In=-1;
  361.   
  362.   /* what direction are we going? */
  363.   if (board[m1]>0)
  364.          {
  365.           sign=Cside;
  366.           
  367.           if (Cside==1) bar=0;
  368.                    else bar=25;  
  369.  
  370.           /* is there a man on the bar?? */
  371.           if ((board[bar]!=0)&&(m1!=0)) return(0);
  372.  
  373.           /* see if all peices are in home base */
  374.           for(i=0;(i<=24)&&(All_In==-1);i++)
  375.               if (board[i]>0) All_In=i;
  376.  
  377.           /* check if can take it off */
  378.           if (m2>24)
  379.              {
  380.              if ((All_In>18)&&
  381.                 ( (m1==(25-p)) || ((25-p)<All_In)&&(m1==All_In) )) return(1);
  382.                                                               else return(0);
  383.              }
  384.           }
  385.      else
  386.          {
  387.           sign=-1;
  388.           /* is there a man on the bar? */
  389.           if ((board[25]!=0)&&(m1!=25)) return(0);
  390.  
  391.           /* see if all peices are in home base */
  392.           for(i=25;(i>=1)&&(All_In==-1);i--)
  393.               if (board[i]<0) All_In=i;
  394.  
  395.           /* see if can take off */
  396.          if (m2==m1)
  397.             {
  398.             if ((All_In<7)&&
  399.                ( (m1==p)|| ((p>All_In)&&(m1==All_In) )))  return(1);
  400.                                                     else  return(0);
  401.             }
  402.           }
  403.  
  404.   /* does dice roll make sense for the move picked? */
  405.   if ((m2-m1)!=(p*sign))  return(0);
  406.  
  407.   /* if spike has more than 1 opponent */
  408.   if (board[m2] * sign < -1)  return(0);
  409.  
  410.   /* I suppose that's all there is..*/
  411.   return(1);
  412.   }
  413.  
  414. /* put a given move onto the board */
  415. update(board,m1,m2,sign)
  416. int board[26],m1,m2,sign;
  417.   {
  418.    int bar;
  419.  
  420.    if (sign>0) bar=0;
  421.           else bar=25;
  422.  
  423.    /* remove the peice from the 'source'  spike */
  424.    
  425.    board[m1]=board[m1]-sign;
  426.  
  427.    /* if taking a peice off, dont go any furthur */
  428.    if ((m2==m1)||(m2>=25)) return(1);
  429.  
  430.    /* add a peice to the 'destination' spike, consider if capturing*/
  431.    
  432.    board[m2]=board[m2]+sign;
  433.  
  434.    if (board[m2]==0) {
  435.                       board[m2    ]=sign;
  436.                       board[25-bar]=board[25-bar]-sign;
  437.                       }
  438.    return(0);
  439.    }
  440.