|
|
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.