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