xref: /csrg-svn/old/btlgammon/btlgammon.c (revision 32224)
1*32224Sbostic #ifndef lint
2*32224Sbostic static char sccsid[] = "@(#)btlgammon.c	1.1 (Berkeley) 09/20/87";
3*32224Sbostic #endif not lint
4*32224Sbostic 
5*32224Sbostic /*
6*32224Sbostic **	The game of Backgammon
7*32224Sbostic */
8*32224Sbostic 
9*32224Sbostic #include	<stdio.h>
10*32224Sbostic 
11*32224Sbostic #define	WHITE		0
12*32224Sbostic #define	BROWN		1
13*32224Sbostic #define	NIL		(-1)
14*32224Sbostic #define	MAXGMOV		10
15*32224Sbostic #define	MAXIMOVES	1000
16*32224Sbostic #define	RULES		"/usr/games/lib/backrules"
17*32224Sbostic 
18*32224Sbostic char	level;		/*'b'=beginner, 'i'=intermediate, 'e'=expert*/
19*32224Sbostic 
20*32224Sbostic int	die1;
21*32224Sbostic int	die2;
22*32224Sbostic int	i;
23*32224Sbostic int	j;
24*32224Sbostic int	l;
25*32224Sbostic int	m;
26*32224Sbostic int	pflg = 1;
27*32224Sbostic int	nobroll = 0;
28*32224Sbostic int	count;
29*32224Sbostic int	imoves;
30*32224Sbostic int	goodmoves[MAXGMOV];
31*32224Sbostic int	probmoves[MAXGMOV];
32*32224Sbostic 
33*32224Sbostic int	brown[] = {		/* brown position table */
34*32224Sbostic 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
35*32224Sbostic 	0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
36*32224Sbostic 	0, 0, 0, 0, 0, 0
37*32224Sbostic };
38*32224Sbostic 
39*32224Sbostic int	white[] = {		/* white position table */
40*32224Sbostic 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
41*32224Sbostic 	0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
42*32224Sbostic 	0, 0, 0, 0, 0, 0
43*32224Sbostic };
44*32224Sbostic 
45*32224Sbostic int	probability[] = {
46*32224Sbostic 	0, 11, 12, 13, 14, 15, 16,
47*32224Sbostic 	06, 05, 04, 03, 02, 01
48*32224Sbostic };
49*32224Sbostic 
50*32224Sbostic struct	{
51*32224Sbostic 	int	pos[4];
52*32224Sbostic 	int	mov[4];
53*32224Sbostic } moves[MAXIMOVES];
54*32224Sbostic 
55*32224Sbostic main()
56*32224Sbostic {
57*32224Sbostic 	int	go[5], tvec[2];
58*32224Sbostic 	int	k, n, pid, ret, rpid, t;
59*32224Sbostic 	char	s[100];
60*32224Sbostic 
61*32224Sbostic 	srand(time(0));
62*32224Sbostic 	go[5] = NIL;
63*32224Sbostic 	fprintf(stdout, "Instructions? ");
64*32224Sbostic 	gets(s);
65*32224Sbostic 	if(*s == 'y')
66*32224Sbostic 		instructions();
67*32224Sbostic 	putchar('\n');
68*32224Sbostic 	fprintf(stdout, "Opponent's level: b - beginner,\n");
69*32224Sbostic 	fprintf(stdout, "i - intermediate, e - expert? ");
70*32224Sbostic 	level='e';
71*32224Sbostic 	gets(s);
72*32224Sbostic 	if(*s == 'b')
73*32224Sbostic 		level = 'b';
74*32224Sbostic 	else if(*s == 'i')
75*32224Sbostic 		level = 'i';
76*32224Sbostic 	putchar('\n');
77*32224Sbostic 	fprintf(stdout, "You will play brown.\n\n");
78*32224Sbostic 	fprintf(stdout, "Would you like to roll your own dice? ");
79*32224Sbostic 	gets(s);
80*32224Sbostic 	putchar('\n');
81*32224Sbostic 	if(*s == 'y')
82*32224Sbostic 		nobroll = 1;
83*32224Sbostic 	fprintf(stdout, "Would you like to go first? ");
84*32224Sbostic 	gets(s);
85*32224Sbostic 	putchar('\n');
86*32224Sbostic 	if(*s == 'y')
87*32224Sbostic 		goto nowhmove;
88*32224Sbostic whitesmv:
89*32224Sbostic 	roll(WHITE);
90*32224Sbostic 	fprintf(stdout, "white rolls %d, %d\n", die1, die2);
91*32224Sbostic 	fprintf(stdout, "white's move is:");
92*32224Sbostic 	if(nextmove(white, brown) == NIL)
93*32224Sbostic 		goto nowhmove;
94*32224Sbostic 	if(piececount(white, 0, 24) == 0){
95*32224Sbostic 		fprintf(stdout, "White wins");
96*32224Sbostic 		if(piececount(brown, 0, 6) != 0)
97*32224Sbostic 			fprintf(stdout, " with a Backgammon!\n");
98*32224Sbostic 		else if (piececount(brown, 0, 24) == 24)
99*32224Sbostic 			fprintf(stdout, " with a Gammon.\n");
100*32224Sbostic 		else
101*32224Sbostic 			fprintf(stdout, ".\n");
102*32224Sbostic 		exit(0);
103*32224Sbostic 	}
104*32224Sbostic nowhmove:
105*32224Sbostic 	if(pflg)
106*32224Sbostic 		prtbrd();
107*32224Sbostic 	roll(BROWN);
108*32224Sbostic retry:
109*32224Sbostic 	fprintf(stdout, "\nYour roll is %d  %d\n", die1, die2);
110*32224Sbostic 	fprintf(stdout, "Move? ");
111*32224Sbostic 	gets(s);
112*32224Sbostic 	switch(*s) {
113*32224Sbostic 		case '\0':			/* empty line */
114*32224Sbostic 			fprintf(stdout, "Brown's move skipped.\n");
115*32224Sbostic 			goto whitesmv;
116*32224Sbostic 
117*32224Sbostic 		case 'b':			/* how many beared off? */
118*32224Sbostic 			fprintf(stdout, "Brown:   %d\n", piececount(brown, 0, 24) - 15);
119*32224Sbostic 			fprintf(stdout, "White:   %d\n", piececount(white, 0, 24) - 15);
120*32224Sbostic 			goto retry;
121*32224Sbostic 
122*32224Sbostic 		case 'p':			/* print board */
123*32224Sbostic 			prtbrd();
124*32224Sbostic 			goto retry;
125*32224Sbostic 
126*32224Sbostic 		case 's':			/* stop auto printing of board */
127*32224Sbostic 			pflg = 0;
128*32224Sbostic 			goto retry;
129*32224Sbostic 
130*32224Sbostic 		case 'r':			/* resume auto printing */
131*32224Sbostic 			pflg = 1;
132*32224Sbostic 			goto retry;
133*32224Sbostic 
134*32224Sbostic 		case 'm':			/* print possible moves */
135*32224Sbostic 			pmoves();
136*32224Sbostic 			goto retry;
137*32224Sbostic 
138*32224Sbostic 		case 'q':			/* i give up */
139*32224Sbostic 			exit(0);
140*32224Sbostic 
141*32224Sbostic 		case '!':			/* escape to Shell */
142*32224Sbostic 			if(s[1] != '\0')
143*32224Sbostic 				system(s+1);
144*32224Sbostic 			else if((pid = fork()) == 0) {
145*32224Sbostic 				execl("/bin/sh", "sh", "-", 0);
146*32224Sbostic 				fprintf(stderr, "back: cannot exec /bin/sh!\n");
147*32224Sbostic 				exit(2);
148*32224Sbostic 			}
149*32224Sbostic 			while((rpid = wait(&ret)) != pid && rpid != -1)
150*32224Sbostic 				;
151*32224Sbostic 			goto retry;
152*32224Sbostic 
153*32224Sbostic 		case '?':			/* well, what can i do? */
154*32224Sbostic 			fprintf(stdout, "<newline>	skip this move\n");
155*32224Sbostic 			fprintf(stdout, "b		number beared off\n");
156*32224Sbostic 			fprintf(stdout, "p		print board\n");
157*32224Sbostic 			fprintf(stdout, "q		quit\n");
158*32224Sbostic 			fprintf(stdout, "r		resume auto print of board\n");
159*32224Sbostic 			fprintf(stdout, "s		stop auto print of board\n");
160*32224Sbostic 			fprintf(stdout, "!		escape to Shell\n");
161*32224Sbostic 			goto retry;
162*32224Sbostic 	}
163*32224Sbostic 	n = sscanf(s,"%d%d%d%d%d",&go[0],&go[1],&go[2],&go[3],&go[4]);
164*32224Sbostic 	if((die1 != die2 && n > 2) || n > 4){
165*32224Sbostic 		fprintf(stdout, "Too many moves.\n");
166*32224Sbostic 		goto retry;
167*32224Sbostic 	}
168*32224Sbostic 	go[n] = NIL;
169*32224Sbostic 	if(*s=='-'){
170*32224Sbostic 		go[0]= -go[0];
171*32224Sbostic 		t=die1;
172*32224Sbostic 		die1=die2;
173*32224Sbostic 		die2=t;
174*32224Sbostic 	}
175*32224Sbostic 	for(k = 0; k < n; k++){
176*32224Sbostic 		if(0 <= go[k] && go[k] <= 24)
177*32224Sbostic 			continue;
178*32224Sbostic 		else{
179*32224Sbostic 			fprintf(stdout, "Move %d illegal.\n", go[k]);
180*32224Sbostic 			goto retry;
181*32224Sbostic 		}
182*32224Sbostic 	}
183*32224Sbostic 	if(play(brown, white, go))
184*32224Sbostic 		goto retry;
185*32224Sbostic 	if(piececount(brown, 0, 24) == 0){
186*32224Sbostic 		fprintf(stdout, "Brown wins");
187*32224Sbostic 		if(piececount(white, 0, 6) != 0)
188*32224Sbostic 			fprintf(stdout, " with a Backgammon.\n");
189*32224Sbostic 		else if(piececount(white, 0, 24) == 24)
190*32224Sbostic 			fprintf(stdout, " with a gammon.\n");
191*32224Sbostic 		else
192*32224Sbostic 			fprintf(stdout, ".\n");
193*32224Sbostic 		exit(0);
194*32224Sbostic 	}
195*32224Sbostic 	goto whitesmv;
196*32224Sbostic }
197*32224Sbostic 
198*32224Sbostic play(player,playee,pos)
199*32224Sbostic int *player,*playee,pos[];
200*32224Sbostic {
201*32224Sbostic 	int	k, n, die, ipos;
202*32224Sbostic 
203*32224Sbostic 	for(k=0; k < player[0]; k++){  /*blots on player[0] must be moved first*/
204*32224Sbostic 		if(pos[k] == NIL)
205*32224Sbostic 			break;
206*32224Sbostic 		if(pos[k] != 0){
207*32224Sbostic 			fprintf(stdout, "Stone on bar must be moved first.\n");
208*32224Sbostic 			return(NIL);
209*32224Sbostic 		}
210*32224Sbostic 	}
211*32224Sbostic 	for(k = 0; (ipos=pos[k]) != NIL; k++){
212*32224Sbostic 		die = k?die2:die1;
213*32224Sbostic 		n = 25-ipos-die;
214*32224Sbostic 		if(player[ipos] == 0)
215*32224Sbostic 			goto badmove;
216*32224Sbostic 		if(n > 0 && playee[n] >= 2)
217*32224Sbostic 			goto badmove;
218*32224Sbostic 		if(n <= 0){
219*32224Sbostic 			if(piececount(player,0,18) != 0)
220*32224Sbostic 				goto badmove;
221*32224Sbostic 			if((ipos+die) != 25 && piececount(player,19,24-die)!=0)
222*32224Sbostic 				goto badmove;
223*32224Sbostic 		}
224*32224Sbostic 		player[ipos]--;
225*32224Sbostic 		player[ipos+die]++;
226*32224Sbostic 	}
227*32224Sbostic 	for(k = 0; pos[k] != NIL; k++){
228*32224Sbostic 		die = k?die2:die1;
229*32224Sbostic 		n = 25-pos[k]-die;
230*32224Sbostic 		if(n>0 && playee[n]==1){
231*32224Sbostic 			playee[n]=0;
232*32224Sbostic 			playee[0]++;
233*32224Sbostic 		}
234*32224Sbostic 	}
235*32224Sbostic 	return(0);
236*32224Sbostic 
237*32224Sbostic badmove:
238*32224Sbostic 	fprintf(stdout, "Move %d illegal.\n", ipos);
239*32224Sbostic 	while(k--){
240*32224Sbostic 		die=k?die2:die1;
241*32224Sbostic 		player[pos[k]]++;
242*32224Sbostic 		player[pos[k]+die]--;
243*32224Sbostic 	}
244*32224Sbostic 	return(NIL);
245*32224Sbostic }
246*32224Sbostic nextmove(player,playee)
247*32224Sbostic int *player,*playee;
248*32224Sbostic {
249*32224Sbostic 	int	k;
250*32224Sbostic 
251*32224Sbostic 	imoves=0;
252*32224Sbostic 	movegen(player,playee);
253*32224Sbostic 	if(die1!=die2){
254*32224Sbostic 		k=die1;
255*32224Sbostic 		die1=die2;
256*32224Sbostic 		die2=k;
257*32224Sbostic 		movegen(player,playee);
258*32224Sbostic 	}
259*32224Sbostic 	if(imoves==0){
260*32224Sbostic 		fprintf(stdout, "no move possible.\n");
261*32224Sbostic 		return(NIL);
262*32224Sbostic 	}
263*32224Sbostic 	k=strategy(player,playee);		/*select kth possible move*/
264*32224Sbostic 	prtmov(k);
265*32224Sbostic 	update(player,playee,k);
266*32224Sbostic 	return(0);
267*32224Sbostic }
268*32224Sbostic prtmov(k)
269*32224Sbostic int k;
270*32224Sbostic {
271*32224Sbostic 	int	n;
272*32224Sbostic 
273*32224Sbostic 	if(k == NIL)
274*32224Sbostic 		fprintf(stdout, "No move possible\n");
275*32224Sbostic 	else for(n = 0; n < 4; n++){
276*32224Sbostic 		if(moves[k].pos[n] == NIL)
277*32224Sbostic 			break;
278*32224Sbostic 		fprintf(stdout, "    %d, %d",25-moves[k].pos[n],moves[k].mov[n]);
279*32224Sbostic 	}
280*32224Sbostic 	fprintf(stdout, "\n");
281*32224Sbostic }
282*32224Sbostic update(player,playee,k)
283*32224Sbostic int *player,*playee,k;
284*32224Sbostic {
285*32224Sbostic 	int	n,t;
286*32224Sbostic 
287*32224Sbostic 	for(n = 0; n < 4; n++){
288*32224Sbostic 		if(moves[k].pos[n] == NIL)
289*32224Sbostic 			break;
290*32224Sbostic 		player[moves[k].pos[n]]--;
291*32224Sbostic 		player[moves[k].pos[n]+moves[k].mov[n]]++;
292*32224Sbostic 		t=25-moves[k].pos[n]-moves[k].mov[n];
293*32224Sbostic 		if(t>0 && playee[t]==1){
294*32224Sbostic 			playee[0]++;
295*32224Sbostic 			playee[t]--;
296*32224Sbostic 		}
297*32224Sbostic 	}
298*32224Sbostic }
299*32224Sbostic piececount(player,startrow,endrow)
300*32224Sbostic int *player,startrow,endrow;
301*32224Sbostic {
302*32224Sbostic 	int	sum;
303*32224Sbostic 
304*32224Sbostic 	sum=0;
305*32224Sbostic 	while(startrow <= endrow)
306*32224Sbostic 		sum += player[startrow++];
307*32224Sbostic 	return(sum);
308*32224Sbostic }
309*32224Sbostic pmoves()
310*32224Sbostic {
311*32224Sbostic 	int	i1, i2;
312*32224Sbostic 
313*32224Sbostic 	fprintf(stdout, "Possible moves are:\n");
314*32224Sbostic 	for(i1 = 0; i1 < imoves; i1++){
315*32224Sbostic 		fprintf(stdout, "\n%d",i1);
316*32224Sbostic 		 for (i2 = 0; i2<4; i2++){
317*32224Sbostic 			if(moves[i1].pos[i2] == NIL)
318*32224Sbostic 				break;
319*32224Sbostic 			fprintf(stdout, "%d, %d",moves[i1].pos[i2],moves[i1].mov[i2]);
320*32224Sbostic 		}
321*32224Sbostic 	}
322*32224Sbostic 	fprintf(stdout, "\n");
323*32224Sbostic }
324*32224Sbostic 
325*32224Sbostic roll(who)
326*32224Sbostic {
327*32224Sbostic 	register n;
328*32224Sbostic 	char	 s[10];
329*32224Sbostic 
330*32224Sbostic 	if(who == BROWN && nobroll) {
331*32224Sbostic 		fprintf(stdout, "Roll? ");
332*32224Sbostic 		gets(s);
333*32224Sbostic 		n = sscanf(s, "%d%d", &die1, &die2);
334*32224Sbostic 		if(n != 2 || die1 < 1 || die1 > 6 || die2 < 1 || die2 > 6)
335*32224Sbostic 			fprintf(stdout, "Illegal - I'll do it!\n");
336*32224Sbostic 		else
337*32224Sbostic 			return;
338*32224Sbostic 	}
339*32224Sbostic 	die1 = ((rand()>>8) % 6) + 1;
340*32224Sbostic 	die2 = ((rand()>>8) % 6) + 1;
341*32224Sbostic }
342*32224Sbostic 
343*32224Sbostic movegen(mover,movee)
344*32224Sbostic int *mover,*movee;
345*32224Sbostic {
346*32224Sbostic 	int	k;
347*32224Sbostic 
348*32224Sbostic 	for(i = 0; i <= 24; i++){
349*32224Sbostic 		count = 0;
350*32224Sbostic 		if(mover[i] == 0)
351*32224Sbostic 			continue;
352*32224Sbostic 		if((k=25-i-die1) > 0 && movee[k] >= 2)
353*32224Sbostic 			if(mover[0] > 0)
354*32224Sbostic 				break;
355*32224Sbostic 		else
356*32224Sbostic 			continue;
357*32224Sbostic 		if(k <= 0){
358*32224Sbostic 			if(piececount(mover, 0, 18) != 0)
359*32224Sbostic 				break;
360*32224Sbostic 			if((i+die1) != 25 && piececount(mover,19,i-1) != 0)
361*32224Sbostic 				break;
362*32224Sbostic 		}
363*32224Sbostic 		mover[i]--;
364*32224Sbostic 		mover[i+die1]++;
365*32224Sbostic 		count = 1;
366*32224Sbostic 		for(j = 0; j <= 24; j++){
367*32224Sbostic 			if(mover[j]==0)
368*32224Sbostic 				continue;
369*32224Sbostic 			if((k=25-j-die2) > 0 && movee[k] >= 2)
370*32224Sbostic 				if(mover[0] > 0)
371*32224Sbostic 					break;
372*32224Sbostic 			else
373*32224Sbostic 				continue;
374*32224Sbostic 			if(k <= 0){
375*32224Sbostic 				if(piececount(mover,0,18) != 0)
376*32224Sbostic 					break;
377*32224Sbostic 				if((j+die2) != 25 && piececount(mover,19,j-1) != 0)
378*32224Sbostic 					break;
379*32224Sbostic 			}
380*32224Sbostic 			mover[j]--;
381*32224Sbostic 			mover[j+die2]++;
382*32224Sbostic 			count = 2;
383*32224Sbostic 			if(die1 != die2){
384*32224Sbostic 				moverecord(mover);
385*32224Sbostic 				if(mover[0] > 0)
386*32224Sbostic 					break;
387*32224Sbostic 				else
388*32224Sbostic 					continue;
389*32224Sbostic 			}
390*32224Sbostic 			for(l = 0; l <= 24; l++){
391*32224Sbostic 				if(mover[l] == 0)
392*32224Sbostic 					continue;
393*32224Sbostic 				if((k=25-l-die1) > 0 && movee[k] >= 2)
394*32224Sbostic 					if(mover[0] > 0)
395*32224Sbostic 						break;
396*32224Sbostic 				else
397*32224Sbostic 					continue;
398*32224Sbostic 				if(k <= 0){
399*32224Sbostic 					if(piececount(mover, 0, 18) != 0)
400*32224Sbostic 						break;
401*32224Sbostic 					if((l+die2) != 25 && piececount(mover,19,l-1) != 0)
402*32224Sbostic 						break;
403*32224Sbostic 				}
404*32224Sbostic 				mover[l]--;
405*32224Sbostic 				mover[l+die1]++;
406*32224Sbostic 				count=3;
407*32224Sbostic 				for(m=0;m<=24;m++){
408*32224Sbostic 					if(mover[m]==0)
409*32224Sbostic 						continue;
410*32224Sbostic 					if((k=25-m-die1) >= 0 && movee[k] >= 2)
411*32224Sbostic 						if(mover[0] > 0)
412*32224Sbostic 							break;
413*32224Sbostic 					else
414*32224Sbostic 						continue;
415*32224Sbostic 					if(k <= 0){
416*32224Sbostic 						if(piececount(mover,0,18) != 0)
417*32224Sbostic 							break;
418*32224Sbostic 						if((m+die2) != 25 && piececount(mover,19,m-1) != 0)
419*32224Sbostic 							break;
420*32224Sbostic 					}
421*32224Sbostic 					count=4;
422*32224Sbostic 					moverecord(mover);
423*32224Sbostic 					if(mover[0] > 0)
424*32224Sbostic 						break;
425*32224Sbostic 				}
426*32224Sbostic 				if(count == 3)
427*32224Sbostic 					moverecord(mover);
428*32224Sbostic 				else{
429*32224Sbostic 					mover[l]++;
430*32224Sbostic 					mover[l+die1]--;
431*32224Sbostic 				}
432*32224Sbostic 				if(mover[0] > 0)
433*32224Sbostic 					break;
434*32224Sbostic 			}
435*32224Sbostic 			if(count == 2)
436*32224Sbostic 				moverecord(mover);
437*32224Sbostic 			else{
438*32224Sbostic 				mover[j]++;
439*32224Sbostic 				mover[j+die1]--;
440*32224Sbostic 			}
441*32224Sbostic 			if(mover[0] > 0)
442*32224Sbostic 				break;
443*32224Sbostic 		}
444*32224Sbostic 		if(count == 1)
445*32224Sbostic 			moverecord(mover);
446*32224Sbostic 		else{
447*32224Sbostic 			mover[i]++;
448*32224Sbostic 			mover[i+die1]--;
449*32224Sbostic 		}
450*32224Sbostic 		if(mover[0] > 0)
451*32224Sbostic 			break;
452*32224Sbostic 	}
453*32224Sbostic }
454*32224Sbostic moverecord(mover)
455*32224Sbostic int *mover;
456*32224Sbostic {
457*32224Sbostic 	int	t;
458*32224Sbostic 
459*32224Sbostic 	if(imoves < MAXIMOVES) {
460*32224Sbostic 		for(t = 0; t <= 3; t++)
461*32224Sbostic 			moves[imoves].pos[t] = NIL;
462*32224Sbostic 		switch(count) {
463*32224Sbostic 		case 4:
464*32224Sbostic 			moves[imoves].pos[3]=m;
465*32224Sbostic 			moves[imoves].mov[3]=die1;
466*32224Sbostic 
467*32224Sbostic 		case 3:
468*32224Sbostic 			moves[imoves].pos[2]=l;
469*32224Sbostic 			moves[imoves].mov[2]=die1;
470*32224Sbostic 
471*32224Sbostic 		case 2:
472*32224Sbostic 			moves[imoves].pos[1]=j;
473*32224Sbostic 			moves[imoves].mov[1]=die2;
474*32224Sbostic 
475*32224Sbostic 		case 1:
476*32224Sbostic 			moves[imoves].pos[0]=i;
477*32224Sbostic 			moves[imoves].mov[0]=die1;
478*32224Sbostic 			imoves++;
479*32224Sbostic 		}
480*32224Sbostic 	}
481*32224Sbostic 	switch(count) {
482*32224Sbostic 	case 4:
483*32224Sbostic 		break;
484*32224Sbostic 
485*32224Sbostic 	case 3:
486*32224Sbostic 		mover[l]++;
487*32224Sbostic 		mover[l+die1]--;
488*32224Sbostic 		break;
489*32224Sbostic 
490*32224Sbostic 	case 2:
491*32224Sbostic 		mover[j]++;
492*32224Sbostic 		mover[j+die2]--;
493*32224Sbostic 		break;
494*32224Sbostic 
495*32224Sbostic 	case 1:
496*32224Sbostic 		mover[i]++;
497*32224Sbostic 		mover[i+die1]--;
498*32224Sbostic 	}
499*32224Sbostic }
500*32224Sbostic 
501*32224Sbostic strategy(player,playee)
502*32224Sbostic int *player,*playee;
503*32224Sbostic {
504*32224Sbostic 	int	k, n, nn, bestval, moveval, prob;
505*32224Sbostic 
506*32224Sbostic 	n = 0;
507*32224Sbostic 	if(imoves == 0)
508*32224Sbostic 		return(NIL);
509*32224Sbostic 	goodmoves[0] = NIL;
510*32224Sbostic 	bestval = -32000;
511*32224Sbostic 	for(k = 0; k < imoves; k++){
512*32224Sbostic 		if((moveval=eval(player,playee,k,&prob)) < bestval)
513*32224Sbostic 			continue;
514*32224Sbostic 		if(moveval > bestval){
515*32224Sbostic 			bestval = moveval;
516*32224Sbostic 			n = 0;
517*32224Sbostic 		}
518*32224Sbostic 		if(n<MAXGMOV){
519*32224Sbostic 			goodmoves[n]=k;
520*32224Sbostic 			probmoves[n++]=prob;
521*32224Sbostic 		}
522*32224Sbostic 	}
523*32224Sbostic 	if(level=='e' && n>1){
524*32224Sbostic 		nn=n;
525*32224Sbostic 		n=0;
526*32224Sbostic 		prob=32000;
527*32224Sbostic 		for(k = 0; k < nn; k++){
528*32224Sbostic 			if((moveval=probmoves[k]) > prob)
529*32224Sbostic 				continue;
530*32224Sbostic 			if(moveval<prob){
531*32224Sbostic 				prob=moveval;
532*32224Sbostic 				n=0;
533*32224Sbostic 			}
534*32224Sbostic 			goodmoves[n]=goodmoves[k];
535*32224Sbostic 			probmoves[n++]=probmoves[k];
536*32224Sbostic 		}
537*32224Sbostic 	}
538*32224Sbostic 	return(goodmoves[(rand()>>4)%n]);
539*32224Sbostic }
540*32224Sbostic 
541*32224Sbostic eval(player,playee,k,prob)
542*32224Sbostic int *player,*playee,k,*prob;
543*32224Sbostic {
544*32224Sbostic 	int	newtry[31], newother[31], *r, *q, *p, n, sum, first;
545*32224Sbostic 	int	ii, lastwhite, lastbrown;
546*32224Sbostic 
547*32224Sbostic 	*prob = sum = 0;
548*32224Sbostic 	r = player+25;
549*32224Sbostic 	p = newtry;
550*32224Sbostic 	q = newother;
551*32224Sbostic 	while(player<r){
552*32224Sbostic 		*p++= *player++;
553*32224Sbostic 		*q++= *playee++;
554*32224Sbostic 	}
555*32224Sbostic 	q=newtry+31;
556*32224Sbostic 	for(p = newtry+25; p < q; p++)		/* zero out spaces for hit pieces */
557*32224Sbostic 		*p = 0;
558*32224Sbostic 	for(n = 0; n < 4; n++){
559*32224Sbostic 		if(moves[k].pos[n] == NIL)
560*32224Sbostic 			break;
561*32224Sbostic 		newtry[moves[k].pos[n]]--;
562*32224Sbostic 		newtry[ii=moves[k].pos[n]+moves[k].mov[n]]++;
563*32224Sbostic 		if(ii<25 && newother[25-ii]==1){
564*32224Sbostic 			newother[25-ii]=0;
565*32224Sbostic 			newother[0]++;
566*32224Sbostic 			if(ii<=15 && level=='e')		/* hit if near other's home */
567*32224Sbostic 				sum++;
568*32224Sbostic 		}
569*32224Sbostic 	}
570*32224Sbostic 	for(lastbrown = 0; newother[lastbrown] == 0; lastbrown++);
571*32224Sbostic 		;
572*32224Sbostic 	for(lastwhite = 0; newtry[lastwhite] == 0; lastwhite++)
573*32224Sbostic 		;
574*32224Sbostic 	lastwhite = 25-lastwhite;
575*32224Sbostic 	if(lastwhite<=6 && lastwhite<lastbrown)
576*32224Sbostic 		sum=1000;
577*32224Sbostic 									/* experts running game. */
578*32224Sbostic 									/* first priority is to */
579*32224Sbostic 									/* get all pieces into */
580*32224Sbostic 									/* white's home */
581*32224Sbostic 	if(lastwhite<lastbrown && level=='e' && lastwhite>6) {
582*32224Sbostic 		for(sum = 1000; lastwhite > 6; lastwhite--)
583*32224Sbostic 			sum = sum-lastwhite*newtry[25-lastwhite];
584*32224Sbostic 	}
585*32224Sbostic 	for(first = 0; first < 25; first++)
586*32224Sbostic 		if(newother[first] != 0)		/*find other's first piece*/
587*32224Sbostic 			break;
588*32224Sbostic 	q = newtry+25;
589*32224Sbostic 	for(p = newtry+1; p < q;)			/* blocked points are good */
590*32224Sbostic 		if(*p++ > 1)
591*32224Sbostic 			sum++;
592*32224Sbostic 	if(first > 5) {					/* only stress removing pieces if */
593*32224Sbostic 							/* homeboard cannot be hit */
594*32224Sbostic 		q = newtry+31;
595*32224Sbostic 		p=newtry+25;
596*32224Sbostic 		for(n = 6; p < q; n--)
597*32224Sbostic 			sum += *p++ * n;			/*remove pieces, but just barely*/
598*32224Sbostic 	}
599*32224Sbostic 	if(level != 'b'){
600*32224Sbostic 		r = newtry+25-first;	/*singles past this point can't be hit*/
601*32224Sbostic 		for(p = newtry+7; p < r; )
602*32224Sbostic 			if(*p++ == 1)		/*singles are bad after 1st 6 points if they can be hit*/
603*32224Sbostic 				sum--;
604*32224Sbostic 		q = newtry+3;
605*32224Sbostic 		for(p = newtry; p < q; )	   /*bad to be on 1st three points*/
606*32224Sbostic 			sum -= *p++;
607*32224Sbostic 	}
608*32224Sbostic 
609*32224Sbostic 	for(n = 1; n <= 4; n++)
610*32224Sbostic 		*prob += n*getprob(newtry,newother,6*n-5,6*n);
611*32224Sbostic 	return(sum);
612*32224Sbostic }
613*32224Sbostic instructions()
614*32224Sbostic {
615*32224Sbostic 	register fd, r;
616*32224Sbostic 	char	 buf[BUFSIZ];
617*32224Sbostic 
618*32224Sbostic 	if((fd = open(RULES, 0)) < 0) {
619*32224Sbostic 		fprintf(stderr, "back: cannot open %s\n", RULES);
620*32224Sbostic 		return;
621*32224Sbostic 	}
622*32224Sbostic 	while(r = read(fd, buf, BUFSIZ))
623*32224Sbostic 		write(1, buf, r);
624*32224Sbostic }
625*32224Sbostic 
626*32224Sbostic getprob(player,playee,start,finish)
627*32224Sbostic int *player,*playee,start,finish;
628*32224Sbostic {			/*returns the probability (times 102) that any
629*32224Sbostic 			  pieces belonging to 'player' and lying between
630*32224Sbostic 			  his points 'start' and 'finish' will be hit
631*32224Sbostic 			  by a piece belonging to playee
632*32224Sbostic 			*/
633*32224Sbostic 	int	k, n, sum;
634*32224Sbostic 
635*32224Sbostic 	sum = 0;
636*32224Sbostic 	for(; start <= finish; start++){
637*32224Sbostic 		if(player[start] == 1){
638*32224Sbostic 			for(k = 1; k <= 12; k++){
639*32224Sbostic 				if((n=25-start-k) < 0)
640*32224Sbostic 					break;
641*32224Sbostic 				if(playee[n] != 0)
642*32224Sbostic 					sum += probability[k];
643*32224Sbostic 			}
644*32224Sbostic 		}
645*32224Sbostic 	}
646*32224Sbostic 	return(sum);
647*32224Sbostic }
648*32224Sbostic prtbrd()
649*32224Sbostic {
650*32224Sbostic 	int	k;
651*32224Sbostic 	static char undersc[]="______________________________________________________";
652*32224Sbostic 
653*32224Sbostic 	fprintf(stdout, "White's Home\n%s\r",undersc);
654*32224Sbostic 	for(k = 1; k <= 6; k++)
655*32224Sbostic 		fprintf(stdout, "%4d",k);
656*32224Sbostic 	fprintf(stdout, "    ");
657*32224Sbostic 	for(k = 7; k <= 12; k++)
658*32224Sbostic 		fprintf(stdout, "%4d",k);
659*32224Sbostic 	putchar('\n');
660*32224Sbostic 	numline(brown, white, 1, 6);
661*32224Sbostic 	fprintf(stdout, "    ");
662*32224Sbostic 	numline(brown, white, 7, 12);
663*32224Sbostic 	putchar('\n');
664*32224Sbostic 	colorline(brown, 'B', white, 'W', 1, 6);
665*32224Sbostic 	fprintf(stdout, "    ");
666*32224Sbostic 	colorline(brown, 'B', white, 'W', 7, 12);
667*32224Sbostic 	putchar('\n');
668*32224Sbostic 	if(white[0] != 0)
669*32224Sbostic 		fprintf(stdout, "%28dW\n",white[0]);
670*32224Sbostic 	else
671*32224Sbostic 		putchar('\n');
672*32224Sbostic 	if(brown[0] != 0)
673*32224Sbostic 		fprintf(stdout, "%28dB\n", brown[0]);
674*32224Sbostic 	else
675*32224Sbostic 		putchar('\n');
676*32224Sbostic 	colorline(white, 'W', brown, 'B', 1, 6);
677*32224Sbostic 	fprintf(stdout, "    ");
678*32224Sbostic 	colorline(white, 'W', brown, 'B', 7, 12);
679*32224Sbostic 	fprintf(stdout, "\n%s\r",undersc);
680*32224Sbostic 	numline(white, brown, 1, 6);
681*32224Sbostic 	fprintf(stdout, "    ");
682*32224Sbostic 	numline(white, brown, 7, 12);
683*32224Sbostic 	putchar('\n');
684*32224Sbostic 	for(k = 24; k >= 19; k--)
685*32224Sbostic 		fprintf(stdout, "%4d",k);
686*32224Sbostic 	fprintf(stdout, "    ");
687*32224Sbostic 	for(k = 18; k >= 13; k--)
688*32224Sbostic 		fprintf(stdout, "%4d",k);
689*32224Sbostic 	fprintf(stdout, "\nBrown's Home\n\n\n\n\n");
690*32224Sbostic }
691*32224Sbostic numline(upcol,downcol,start,fin)
692*32224Sbostic int *upcol,*downcol,start,fin;
693*32224Sbostic {
694*32224Sbostic 	int	k, n;
695*32224Sbostic 
696*32224Sbostic 	for(k = start; k <= fin; k++){
697*32224Sbostic 		if((n = upcol[k]) != 0 || (n = downcol[25-k]) != 0)
698*32224Sbostic 			fprintf(stdout, "%4d", n);
699*32224Sbostic 		else
700*32224Sbostic 			fprintf(stdout, "    ");
701*32224Sbostic 	}
702*32224Sbostic }
703*32224Sbostic colorline(upcol,c1,downcol,c2,start,fin)
704*32224Sbostic int *upcol,*downcol,start,fin;
705*32224Sbostic char c1,c2;
706*32224Sbostic {
707*32224Sbostic 	int	k;
708*32224Sbostic 	char 	c;
709*32224Sbostic 
710*32224Sbostic 	for(k = start; k <= fin; k++){
711*32224Sbostic 		c = ' ';
712*32224Sbostic 		if(upcol[k] != 0)
713*32224Sbostic 			c = c1;
714*32224Sbostic 		if(downcol[25-k] != 0)
715*32224Sbostic 			c = c2;
716*32224Sbostic 		fprintf(stdout, "   %c",c);
717*32224Sbostic 	}
718*32224Sbostic }
719