home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / games / backgammon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-25  |  12.9 KB  |  585 lines

  1. # include <stdio.h>
  2.  
  3. #
  4. #define NIL (-1)
  5. #define MAXGMOV 10
  6. #define MAXIMOVES 1000
  7.     char level;        /*'b'=beginner, 'i'=intermediate, 'e'=expert*/
  8. int die1;
  9. int die2;
  10. int i;
  11. int j;
  12. int l;
  13. int m;
  14. int count;
  15. int red[]     {0,2,0,0,0,0,0,0,0,0,0,0,5,
  16.          0,0,0,0,3,0,5,0,0,0,0,0,
  17.          0,0,0,0,0,0};
  18. int white[]   {0,2,0,0,0,0,0,0,0,0,0,0,5,
  19.          0,0,0,0,3,0,5,0,0,0,0,0,
  20.          0,0,0,0,0,0};
  21. int probability[]{0,11,12,13,14,15,16,
  22.             06,05,04,03,02,01};
  23. int imoves;
  24. int goodmoves[MAXGMOV] ;
  25. int probmoves[MAXGMOV] ;
  26. struct {int pos[4],mov[4];} moves[MAXIMOVES] ;
  27.  
  28. main()
  29. {
  30.     int t,k,n,go[5];
  31.     char s[100];
  32.     go[5]=NIL;
  33.     srand();
  34.     printf( "Do you want instructions? Type 'y' for yes,\n");
  35.     printf( "anything else means no.?? ");
  36.     getstr(s);
  37.     if(*s=='y')instructions();
  38.     printf( "Choose the level of your oppponent.\n");
  39.     printf( "Type 'b' for beginner, or 'i' for intermediate.\n");
  40.     printf( "Anything else gets you an expert.?? ");
  41.     level='e';
  42.     getstr(s);
  43.     if(*s=='b')level='b';
  44.     else if(*s=='i')level='i';
  45.     printf( "You will play red. Do you wan't to move first?\n");
  46.     printf( "Type 'y' for yes, anything else means no.?? ");
  47.     getstr(s);
  48.     if(*s=='y')goto nowhmove;
  49. whitesmv:
  50.     roll();
  51.     printf( "white rolls %d,%d\n",die1,die2);
  52.     printf( "white's move is:");
  53.     if(nextmove(white,red)==NIL)goto nowhmove;
  54.     if(piececount(white,0,24)==0){
  55.         printf( "White wins\n");
  56.         printf( "Aren't you ashamed. You've been beaten by a computer.\n");
  57.         exit();
  58.     }
  59. nowhmove:
  60.     prtbrd();
  61.  
  62.     roll();
  63. retry:
  64.     printf( "your roll is %d,  %d\n",die1,die2);
  65.     printf( "your move, please?? ");
  66.     getstr(s);
  67.     if(*s==0){
  68.         printf( "red's move skipped\n");
  69.         goto whitesmv;
  70.     }
  71.     n=sscanf(s,"%d%d%d%d%d",&go[0],&go[1],&go[2],&go[3],&go[4]);
  72.     if((die1!=die2&&n>2)||n>4){
  73.         printf( "you've made too many moves\n");
  74.         goto retry;
  75.     }
  76.     go[n]=NIL;
  77.     if(*s=='-'){
  78.         go[0]= -go[0];
  79.         t=die1;
  80.         die1=die2;
  81.         die2=t;
  82.     }
  83.     for(k=0;k<n;k++){
  84.         if(0<=go[k] && go[k]<=24)continue;
  85.         else{
  86.         printf( "move %d is illegal\n",go[k]);
  87.         goto retry;
  88.         }
  89.     }
  90.     if(play(red,white,go))goto retry;
  91.     if(piececount(red,0,24)==0){
  92.         printf( "Red wins.\n");
  93.         printf( "Congratulations! You have just defeated a dumb machine.\n");
  94.         exit();
  95.     }
  96.     goto whitesmv;
  97. }
  98.  
  99. getstr(s)
  100. char *s;
  101. {
  102.     while((*s=getchar())!='\n')s++;
  103.     *s=0;
  104. }
  105.  
  106. play(player,playee,pos)
  107. int *player,*playee,pos[];
  108. {
  109.     int k,n,die,ipos;
  110.     for(k=0;k<player[0];k++){  /*blots on player[0] must be moved first*/
  111.         if(pos[k]==NIL)break;
  112.         if(pos[k]!=0){
  113.         printf( "piece on position 0 must be moved first\n");
  114.         return(-1);
  115.         }
  116.     }
  117.     for(k=0;(ipos=pos[k])!=NIL;k++){
  118.         die=k?die2:die1;
  119.         n=25-ipos-die;
  120.         if(player[ipos]==0)goto badmove;
  121.         if(n>0&&playee[n]>=2)goto badmove;
  122.         if(n<=0){
  123.         if(piececount(player,0,18)!=0)goto badmove;
  124.         if((ipos+die)!=25&&
  125.             piececount(player,19,24-die)!=0)goto badmove;
  126.         }
  127.         player[ipos]--;
  128.         player[ipos+die]++;
  129.     }
  130.     for(k=0;pos[k]!=NIL;k++){
  131.         die=k?die2:die1;
  132.         n=25-pos[k]-die;
  133.         if(n>0 && playee[n]==1){
  134.         playee[n]=0;
  135.         playee[0]++;
  136.         }
  137.     }
  138.     return(0);
  139.  
  140. badmove:
  141.     printf( "Move %d is not legal.\n",ipos);
  142.     while(k--){
  143.         die=k?die2:die1;
  144.         player[pos[k]]++;
  145.         player[pos[k]+die]--;
  146.     }
  147.     return(-1);
  148. }
  149. nextmove(player,playee)
  150. int *player,*playee;
  151. {
  152.     int k;
  153.     imoves=0;
  154.     movegen(player,playee);
  155.     if(die1!=die2){
  156.     k=die1;
  157.     die1=die2;
  158.     die2=k;
  159.     movegen(player,playee);
  160.     }
  161.     if(imoves==0){
  162.         printf( "roll was %d,%d; no white move possible\n",die1,die2);
  163.         return(NIL);
  164.     }
  165.     k=strategy(player,playee);        /*select kth possible move*/
  166.     prtmov(k);
  167.     update(player,playee,k);
  168.     return(0);
  169. }
  170. prtmov(k)
  171. int k;
  172. {
  173.     int n;
  174.     if(k==NIL)printf( "no move possible\n");
  175.     else for(n=0;n<4;n++){
  176.         if(moves[k].pos[n]==NIL)break;
  177.         printf( "    %d, %d",25-moves[k].pos[n],moves[k].mov[n]);
  178.     }
  179.     printf( "\n");
  180. }
  181. update(player,playee,k)
  182. int *player,*playee,k;
  183. {
  184.     int n,t;
  185.     for(n=0;n<4;n++){
  186.         if(moves[k].pos[n]==NIL)break;
  187.         player[moves[k].pos[n]]--;
  188.         player[moves[k].pos[n]+moves[k].mov[n]]++;
  189.         t=25-moves[k].pos[n]-moves[k].mov[n];
  190.         if(t>0 && playee[t]==1){
  191.         playee[0]++;
  192.         playee[t]--;
  193.         }
  194.     }
  195. }
  196. piececount(player,startrow,endrow)
  197. int *player,startrow,endrow;
  198. {
  199.     int sum;
  200.     sum=0;
  201.     while(startrow<=endrow)
  202.     sum=+player[startrow++];
  203.     return(sum);
  204. }
  205. /*
  206. prtmovs()
  207. {
  208.     int i1,i2;
  209.     printf( "possible moves are\n");
  210.     for(i1=0;i1<imoves;i1++){
  211.         printf( "\n%d",i1);
  212.         for(i2=0;i2<4;i2++){
  213.             if(moves[i1].pos[i2]==NIL)break;
  214.             printf( "%d, %d",moves[i1].pos[i2],moves[i1].mov[i2]);
  215.         }
  216.     }
  217.     printf( "\n");
  218. }
  219. */
  220.  
  221. roll()
  222. {
  223.     extern int die1,die2;
  224.     die1=(rand()>>8)%6+1;
  225.     die2=(rand()>>8)%6+1;
  226. }
  227.  
  228. movegen(mover,movee)
  229. int *mover,*movee;
  230. {
  231.     extern int i,j,l,m,count;
  232.     extern int die1,die2;
  233.     int k;
  234.     for(i=0;i<=24;i++){
  235.         count=0;
  236.         if(mover[i]==0)continue;
  237.         if((k=25-i-die1)>0&&movee[k]>=2)
  238.             if(mover[0]>0)break;
  239.             else continue;
  240.         if(k<=0){
  241.             if(piececount(mover,0,18)!=0)break;
  242.             if((i+die1)!=25&&
  243.                 piececount(mover,19,24-die1)!=0)break;
  244.         }
  245.         mover[i]--;
  246.         mover[i+die1]++;
  247.         count=1;
  248.         for(j=0;j<=24;j++){
  249.             if(mover[j]==0)continue;
  250.             if((k=25-j-die2)>0&&movee[k]>=2)
  251.                 if(mover[0]>0)break;
  252.                 else continue;
  253.             if(k<=0){
  254.                 if(piececount(mover,0,18)!=0)break;
  255.                 if((j+die2)!=25&&
  256.                     piececount(mover,19,24-die2)!=0)break;
  257.             }
  258.             mover[j]--;
  259.             mover[j+die2]++;
  260.             count=2;
  261.             if(die1!=die2){
  262.                 moverecord(mover);
  263.                 if(mover[0]>0)break;
  264.                 else continue;
  265.             }
  266.             for(l=0;l<=24;l++){
  267.                 if(mover[l]==0)continue;
  268.                 if((k=25-l-die1)>0&&movee[k]>=2)
  269.                 if(mover[0]>0)break;
  270.                 else continue;
  271.                 if(k<=0){
  272.                 if(piececount(mover,0,18)!=0)break;
  273.                 if((l+die2)!=25&&
  274.                     piececount(mover,19,24-die1)!=0)break;
  275.                 }
  276.                 mover[l]--;
  277.                 mover[l+die1]++;
  278.                 count=3;
  279.                 for(m=0;m<=24;m++){
  280.                 if(mover[m]==0)continue;
  281.                 if((k=25-m-die1)>=0&&movee[k]>=2)
  282.                     if(mover[0]>0)break;
  283.                     else continue;
  284.                 if(k<=0){
  285.                     if(piececount(mover,0,18)!=0)break;
  286.                     if((m+die2)!=25&&
  287.                         piececount(mover,19,24-die1)!=0)break;
  288.                 }
  289.                 count=4;
  290.                 moverecord(mover);
  291.                 if(mover[0]>0)break;
  292.                 }
  293.                 if(count==3)moverecord(mover);
  294.                 else{
  295.                 mover[l]++;
  296.                 mover[l+die1]--;
  297.                 }
  298.                 if(mover[0]>0)break;
  299.             }
  300.             if(count==2)moverecord(mover);
  301.             else{
  302.                 mover[j]++;
  303.                 mover[j+die1]--;
  304.             }
  305.             if(mover[0]>0)break;
  306.         }
  307.         if(count==1)moverecord(mover);
  308.         else{
  309.             mover[i]++;
  310.             mover[i+die1]--;
  311.         }
  312.         if(mover[0]>0)break;
  313.     }
  314. }
  315. moverecord(mover)
  316. int *mover;
  317. {
  318.     extern int i,j,l,m,imoves,count;
  319.     int t;
  320.     if(imoves>=MAXIMOVES)goto undo;;
  321.     for(t=0;t<=3;t++)
  322.         moves[imoves].pos[t]= NIL;
  323.     switch(count){
  324. case 4:
  325.         moves[imoves].pos[3]=m;
  326.         moves[imoves].mov[3]=die1;
  327. case 3:
  328.         moves[imoves].pos[2]=l;
  329.         moves[imoves].mov[2]=die1;
  330. case 2:
  331.         moves[imoves].pos[1]=j;
  332.         moves[imoves].mov[1]=die2;
  333. case 1:
  334.         moves[imoves].pos[0]=i;
  335.         moves[imoves].mov[0]=die1;
  336.         imoves++;
  337.     }
  338. undo:
  339.     switch(count){
  340. case 4:
  341.         break;
  342. case 3:
  343.         mover[l]++;
  344.         mover[l+die1]--;
  345.         break;
  346. case 2:
  347.         mover[j]++;
  348.         mover[j+die2]--;
  349.         break;
  350. case 1:
  351.         mover[i]++;
  352.         mover[i+die1]--;
  353.     }
  354. }
  355.  
  356.  
  357. strategy(player,playee)
  358. int *player,*playee;
  359. {
  360.     extern char level;
  361.     int k,n,nn,bestval,moveval,prob;
  362.     n=0;
  363.     if(imoves==0)return(NIL);
  364.     goodmoves[0]=NIL;
  365.     bestval= -32000;
  366.     for(k=0;k<imoves;k++){
  367.         if((moveval=eval(player,playee,k,&prob))<bestval)continue;
  368.         if(moveval>bestval){
  369.         bestval=moveval;
  370.         n=0;
  371.         }
  372.         if(n<MAXGMOV){
  373.         goodmoves[n]=k;
  374.         probmoves[n++]=prob;
  375.         }
  376.     }
  377.     if(level=='e' && n>1){
  378.         nn=n;
  379.         n=0;
  380.         prob=32000;
  381.         for(k=0;k<nn;k++){
  382.         if((moveval=probmoves[k])>prob)continue;
  383.         if(moveval<prob){
  384.             prob=moveval;
  385.             n=0;
  386.         }
  387.         goodmoves[n]=goodmoves[k];
  388.         probmoves[n++]=probmoves[k];
  389.         }
  390.     }
  391.     return(goodmoves[(rand()>>4)%n]);
  392. }
  393.  
  394. eval(player,playee,k,prob)
  395. int *player,*playee,k,*prob;
  396. {
  397.     extern char level;
  398.     int newtry[31],newother[31],*r,*q,*p,n,sum,first;
  399.     int ii,lastwhite,lastred;
  400.     *prob=sum=0;
  401.     r=player+25;
  402.     p=newtry;
  403.     q=newother;
  404.     while(player<r){
  405.         *p++= *player++;
  406.         *q++= *playee++;
  407.     }
  408.     q=newtry+31;
  409.     for(p=newtry+25;p<q;) *p++ = 0;    /*zero out spaces for hit pieces*/
  410.     for(n=0;n<4;n++){
  411.         if(moves[k].pos[n]==NIL)break;
  412.         newtry[moves[k].pos[n]]--;
  413.         newtry[ii=moves[k].pos[n]+moves[k].mov[n]]++;
  414.         if(ii<25 && newother[25-ii]==1){
  415.         newother[25-ii]=0;
  416.         newother[0]++;
  417.         if(ii<=15 && level=='e')sum++;    /*hit if near other's home*/
  418.         }
  419.     }
  420.     for(lastred=0;newother[lastred]==0;lastred++);
  421.     for(lastwhite=0;newtry[lastwhite]==0;lastwhite++);
  422.     lastwhite=25-lastwhite;
  423.     if(lastwhite<=6 && lastwhite<lastred)sum=1000;
  424.     if(lastwhite<lastred && level=='e'
  425.         && lastwhite>6){            /*expert's running game.
  426.                           First priority to get all
  427.                           pieces into white's home*/
  428.         for(sum=1000;lastwhite>6;lastwhite--)
  429.         sum=sum-lastwhite*newtry[25-lastwhite];
  430.     }
  431.     for(first=0;first<25;first++)
  432.         if(newother[first]!=0)break;    /*find other's first piece*/
  433.     q=newtry+25;
  434.     for(p=newtry+1;p<q;)if(*p++ > 1)sum++;    /*blocked points are good*/
  435.     if(first>5){    /*only stress removing pieces if homeboard
  436.               cannot be hit
  437.             */
  438.         q=newtry+31;
  439.         p=newtry+25;
  440.         for(n=6;p<q;n--)
  441.         sum=+ *p++ * n;    /*remove pieces, but just barely*/
  442.     }
  443.     if(level!='b'){
  444.         r=newtry+25-first;    /*singles past this point can't be hit*/
  445.         for(p=newtry+7;p<r;)
  446.         if(*p++ == 1)sum--;    /*singles are bad after 1st 6 points
  447.                       if they can be hit*/
  448.         q=newtry+3;
  449.         for(p=newtry;p<q;)sum=- *p++;  /*bad to be on 1st three points*/
  450.     }
  451.  
  452.     for(n=1;n<=4;n++)
  453.         *prob=+ n*getprob(newtry,newother,6*n-5,6*n);
  454.     return(sum);
  455. }
  456. instructions()
  457. {
  458.     printf( "To play backgammon, type the numbers of the points\n");
  459.     printf( "from which pieces are to be moved. Thus, if the\n");
  460.     printf( "roll is '3,5', typing '2 6' will move a piece\n");
  461.     printf( "from point 2 three spaces to point 5,\n");
  462.     printf( "and a piece from point 6 forward to\n");
  463.     printf( "point 11.  If the moves must be made in the\n");
  464.     printf( "opposite order, the first character typed must\n");
  465.     printf( "be a minus ('-'). Thus, typing\n");
  466.     printf( "'-2 6' moves the piece on point 2\n");
  467.     printf( "by 5, and the piece on point 6 by 3.\n");
  468.     printf( "If you want to move a single piece several times,\n");
  469.     printf( "the sequence of points from which it is to be\n");
  470.     printf( "moved must be typed. Thus '14 17' will move\n");
  471.     printf( "a piece from point 14 to point 17 and thence to\n");
  472.     printf( "to point 22.\n");
  473.     printf( "If a double is rolled, you should type four numbers.\n");
  474.     printf( "Red pieces that have been removed from the board by\n");
  475.     printf( "being hit by white are on point 0 and\n");
  476.     printf( "must be brought in before any other move can be made.\n");
  477.     printf( "White pieces that are hit are removed to point 25.\n");
  478.     printf( "You will not be allowed to make an illegal move, or\n");
  479.     printf( "to make too many moves. However, if you make too\n");
  480.     printf( "few moves, the program does not care. In particular\n");
  481.     printf( "you may skip your turn by typing a 'new-line'\n");
  482.     printf( "all by itself.\n\n");
  483. }
  484.  
  485. getprob(player,playee,start,finish)
  486. int *player,*playee,start,finish;
  487. {            /*returns the probability (times 102) that any
  488.               pieces belonging to 'player' and lying between
  489.               his points 'start' and 'finish' will be hit
  490.               by a piece belonging to playee
  491.             */
  492.     int k,n,sum;
  493.     sum=0;
  494.     for(;start<=finish;start++){
  495.         if(player[start]==1){
  496.         for(k=1;k<=12;k++){
  497.             if((n=25-start-k)<0)break;
  498.             if(playee[n]!=0)sum=+probability[k];
  499.         }
  500.         }
  501.     }
  502.     return(sum);
  503. }
  504. prtbrd()
  505. {
  506.     int k;
  507.     printf( "White's Home\n");
  508.     for(k=1;k<=6;k++)
  509.         printf( "%4d",k);
  510.     printf( "    ");
  511.     for(k=7;k<=12;k++)printf( "%4d",k);
  512.     putchar('\r' );
  513.     for(k=1;k<=54;k++)putchar('_' );
  514.     putchar('\n' );
  515.     numline(red,white,1,6);
  516.     printf( "    ");
  517.     numline(red,white,7,12);
  518.     putchar('\n' );
  519.     colorline(red,'R',white,'W',1,6);
  520.     printf( "    ");
  521.     colorline(red,'R',white,'W',7,12);
  522.     putchar('\n' );
  523.     if(white[0]!=0)printf( "%28dW\n",white[0]);
  524.     else putchar('\n' );
  525.     if(red[0]!=0)printf( "%28dR\n",red[0]);
  526.     else putchar('\n' );
  527.     colorline(white,'W',red,'R',1,6);
  528.     printf( "    ");
  529.     colorline(white,'W',red,'R',7,12);
  530.     putchar('\n' );
  531.     numline(white,red,1,6);
  532.     printf( "    ");
  533.     numline(white,red,7,12);
  534.     putchar('\r' );
  535.     for(k=1;k<=54;k++)putchar('_' );
  536.     putchar('\n' );
  537.     for(k=24;k>=19;k--)printf( "%4d",k);
  538.     printf( "    ");
  539.     for(k=18;k>=13;k--)printf( "%4d",k);
  540.     printf( "\nRed's Home\n\n\n\n\n");
  541. }
  542. numline(upcol,downcol,start,fin)
  543. int *upcol,*downcol,start,fin;
  544. {
  545.     int k,n;
  546.     for(k=start;k<=fin;k++){
  547.         if((n=upcol[k])!=0 || (n=downcol[25-k])!=0)printf( "%4d",n);
  548.         else printf( "    ");
  549.     }
  550. }
  551. colorline(upcol,c1,downcol,c2,start,fin)
  552. int *upcol,*downcol,start,fin;
  553. char c1,c2;
  554. {
  555.     int k;
  556.     char c;
  557.     for(k=start;k<=fin;k++){
  558.         c=' ';
  559.         if(upcol[k]!=0)c=c1;
  560.         if(downcol[25-k]!=0)c=c2;
  561.     printf( "   %c",c);
  562.     }
  563. }
  564.  
  565. int rrno 0;
  566.  
  567. srand(){
  568.     rrno = _look( 0x40000 );
  569.     _store( 0x40000, rrno+1 );
  570.     }
  571.  
  572. rand(){
  573.     rrno =* 0106273;
  574.     rrno =+ 020202;
  575.     return( rrno & 077777 );
  576.     }
  577.  
  578. _look(p) int *p; {
  579.     return( *p );
  580.     }
  581.  
  582. _store( p, numb ) int *p; {
  583.     *p = numb;
  584.     }
  585.