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