xref: /original-bsd/old/btlgammon/btlgammon.c (revision 32792795)
18ccff702Sbostic #ifndef lint
2*32792795Sbostic static char sccsid[] = "@(#)btlgammon.c	1.2 (Berkeley) 09/20/87";
38ccff702Sbostic #endif not lint
48ccff702Sbostic 
58ccff702Sbostic /*
68ccff702Sbostic **	The game of Backgammon
78ccff702Sbostic */
88ccff702Sbostic 
98ccff702Sbostic #include	<stdio.h>
108ccff702Sbostic 
118ccff702Sbostic #define	WHITE		0
128ccff702Sbostic #define	BROWN		1
138ccff702Sbostic #define	NIL		(-1)
148ccff702Sbostic #define	MAXGMOV		10
158ccff702Sbostic #define	MAXIMOVES	1000
168ccff702Sbostic #define	RULES		"/usr/games/lib/backrules"
178ccff702Sbostic 
188ccff702Sbostic char	level;		/*'b'=beginner, 'i'=intermediate, 'e'=expert*/
198ccff702Sbostic 
208ccff702Sbostic int	die1;
218ccff702Sbostic int	die2;
228ccff702Sbostic int	i;
238ccff702Sbostic int	j;
248ccff702Sbostic int	l;
258ccff702Sbostic int	m;
268ccff702Sbostic int	pflg = 1;
278ccff702Sbostic int	nobroll = 0;
288ccff702Sbostic int	count;
298ccff702Sbostic int	imoves;
308ccff702Sbostic int	goodmoves[MAXGMOV];
318ccff702Sbostic int	probmoves[MAXGMOV];
328ccff702Sbostic 
338ccff702Sbostic int	brown[] = {		/* brown position table */
348ccff702Sbostic 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
358ccff702Sbostic 	0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
368ccff702Sbostic 	0, 0, 0, 0, 0, 0
378ccff702Sbostic };
388ccff702Sbostic 
398ccff702Sbostic int	white[] = {		/* white position table */
408ccff702Sbostic 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
418ccff702Sbostic 	0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
428ccff702Sbostic 	0, 0, 0, 0, 0, 0
438ccff702Sbostic };
448ccff702Sbostic 
458ccff702Sbostic int	probability[] = {
468ccff702Sbostic 	0, 11, 12, 13, 14, 15, 16,
478ccff702Sbostic 	06, 05, 04, 03, 02, 01
488ccff702Sbostic };
498ccff702Sbostic 
508ccff702Sbostic struct	{
518ccff702Sbostic 	int	pos[4];
528ccff702Sbostic 	int	mov[4];
538ccff702Sbostic } moves[MAXIMOVES];
548ccff702Sbostic 
main()558ccff702Sbostic main()
568ccff702Sbostic {
578ccff702Sbostic 	int	go[5], tvec[2];
588ccff702Sbostic 	int	k, n, pid, ret, rpid, t;
598ccff702Sbostic 	char	s[100];
608ccff702Sbostic 
618ccff702Sbostic 	srand(time(0));
628ccff702Sbostic 	go[5] = NIL;
638ccff702Sbostic 	fprintf(stdout, "Instructions? ");
648ccff702Sbostic 	gets(s);
658ccff702Sbostic 	if(*s == 'y')
668ccff702Sbostic 		instructions();
678ccff702Sbostic 	putchar('\n');
688ccff702Sbostic 	fprintf(stdout, "Opponent's level: b - beginner,\n");
698ccff702Sbostic 	fprintf(stdout, "i - intermediate, e - expert? ");
708ccff702Sbostic 	level='e';
718ccff702Sbostic 	gets(s);
728ccff702Sbostic 	if(*s == 'b')
738ccff702Sbostic 		level = 'b';
748ccff702Sbostic 	else if(*s == 'i')
758ccff702Sbostic 		level = 'i';
768ccff702Sbostic 	putchar('\n');
778ccff702Sbostic 	fprintf(stdout, "You will play brown.\n\n");
788ccff702Sbostic 	fprintf(stdout, "Would you like to roll your own dice? ");
798ccff702Sbostic 	gets(s);
808ccff702Sbostic 	putchar('\n');
818ccff702Sbostic 	if(*s == 'y')
828ccff702Sbostic 		nobroll = 1;
838ccff702Sbostic 	fprintf(stdout, "Would you like to go first? ");
848ccff702Sbostic 	gets(s);
858ccff702Sbostic 	putchar('\n');
868ccff702Sbostic 	if(*s == 'y')
878ccff702Sbostic 		goto nowhmove;
888ccff702Sbostic whitesmv:
898ccff702Sbostic 	roll(WHITE);
908ccff702Sbostic 	fprintf(stdout, "white rolls %d, %d\n", die1, die2);
918ccff702Sbostic 	fprintf(stdout, "white's move is:");
928ccff702Sbostic 	if(nextmove(white, brown) == NIL)
938ccff702Sbostic 		goto nowhmove;
948ccff702Sbostic 	if(piececount(white, 0, 24) == 0){
958ccff702Sbostic 		fprintf(stdout, "White wins");
968ccff702Sbostic 		if(piececount(brown, 0, 6) != 0)
978ccff702Sbostic 			fprintf(stdout, " with a Backgammon!\n");
988ccff702Sbostic 		else if (piececount(brown, 0, 24) == 24)
998ccff702Sbostic 			fprintf(stdout, " with a Gammon.\n");
1008ccff702Sbostic 		else
1018ccff702Sbostic 			fprintf(stdout, ".\n");
1028ccff702Sbostic 		exit(0);
1038ccff702Sbostic 	}
1048ccff702Sbostic nowhmove:
1058ccff702Sbostic 	if(pflg)
1068ccff702Sbostic 		prtbrd();
1078ccff702Sbostic 	roll(BROWN);
1088ccff702Sbostic retry:
1098ccff702Sbostic 	fprintf(stdout, "\nYour roll is %d  %d\n", die1, die2);
1108ccff702Sbostic 	fprintf(stdout, "Move? ");
1118ccff702Sbostic 	gets(s);
1128ccff702Sbostic 	switch(*s) {
1138ccff702Sbostic 		case '\0':			/* empty line */
1148ccff702Sbostic 			fprintf(stdout, "Brown's move skipped.\n");
1158ccff702Sbostic 			goto whitesmv;
1168ccff702Sbostic 
1178ccff702Sbostic 		case 'b':			/* how many beared off? */
1188ccff702Sbostic 			fprintf(stdout, "Brown:   %d\n", piececount(brown, 0, 24) - 15);
1198ccff702Sbostic 			fprintf(stdout, "White:   %d\n", piececount(white, 0, 24) - 15);
1208ccff702Sbostic 			goto retry;
1218ccff702Sbostic 
1228ccff702Sbostic 		case 'p':			/* print board */
1238ccff702Sbostic 			prtbrd();
1248ccff702Sbostic 			goto retry;
1258ccff702Sbostic 
1268ccff702Sbostic 		case 's':			/* stop auto printing of board */
1278ccff702Sbostic 			pflg = 0;
1288ccff702Sbostic 			goto retry;
1298ccff702Sbostic 
1308ccff702Sbostic 		case 'r':			/* resume auto printing */
1318ccff702Sbostic 			pflg = 1;
1328ccff702Sbostic 			goto retry;
1338ccff702Sbostic 
1348ccff702Sbostic 		case 'm':			/* print possible moves */
1358ccff702Sbostic 			pmoves();
1368ccff702Sbostic 			goto retry;
1378ccff702Sbostic 
1388ccff702Sbostic 		case 'q':			/* i give up */
1398ccff702Sbostic 			exit(0);
1408ccff702Sbostic 
1418ccff702Sbostic 		case '!':			/* escape to Shell */
142*32792795Sbostic #ifdef ADD_A_MAJOR_SECURITY_HOLE
1438ccff702Sbostic 			if(s[1] != '\0')
1448ccff702Sbostic 				system(s+1);
145*32792795Sbostic 			else
146*32792795Sbostic #endif
147*32792795Sbostic 			if (!(pid = vfork()) == 0) {
148*32792795Sbostic 				(void)setuid(getuid());
149*32792795Sbostic 				(void)setgid(getgid());
1508ccff702Sbostic 				execl("/bin/sh", "sh", "-", 0);
1518ccff702Sbostic 				fprintf(stderr, "back: cannot exec /bin/sh!\n");
1528ccff702Sbostic 				exit(2);
1538ccff702Sbostic 			}
1548ccff702Sbostic 			while((rpid = wait(&ret)) != pid && rpid != -1)
1558ccff702Sbostic 				;
1568ccff702Sbostic 			goto retry;
1578ccff702Sbostic 
1588ccff702Sbostic 		case '?':			/* well, what can i do? */
1598ccff702Sbostic 			fprintf(stdout, "<newline>	skip this move\n");
1608ccff702Sbostic 			fprintf(stdout, "b		number beared off\n");
1618ccff702Sbostic 			fprintf(stdout, "p		print board\n");
1628ccff702Sbostic 			fprintf(stdout, "q		quit\n");
1638ccff702Sbostic 			fprintf(stdout, "r		resume auto print of board\n");
1648ccff702Sbostic 			fprintf(stdout, "s		stop auto print of board\n");
1658ccff702Sbostic 			fprintf(stdout, "!		escape to Shell\n");
1668ccff702Sbostic 			goto retry;
1678ccff702Sbostic 	}
1688ccff702Sbostic 	n = sscanf(s,"%d%d%d%d%d",&go[0],&go[1],&go[2],&go[3],&go[4]);
1698ccff702Sbostic 	if((die1 != die2 && n > 2) || n > 4){
1708ccff702Sbostic 		fprintf(stdout, "Too many moves.\n");
1718ccff702Sbostic 		goto retry;
1728ccff702Sbostic 	}
1738ccff702Sbostic 	go[n] = NIL;
1748ccff702Sbostic 	if(*s=='-'){
1758ccff702Sbostic 		go[0]= -go[0];
1768ccff702Sbostic 		t=die1;
1778ccff702Sbostic 		die1=die2;
1788ccff702Sbostic 		die2=t;
1798ccff702Sbostic 	}
1808ccff702Sbostic 	for(k = 0; k < n; k++){
1818ccff702Sbostic 		if(0 <= go[k] && go[k] <= 24)
1828ccff702Sbostic 			continue;
1838ccff702Sbostic 		else{
1848ccff702Sbostic 			fprintf(stdout, "Move %d illegal.\n", go[k]);
1858ccff702Sbostic 			goto retry;
1868ccff702Sbostic 		}
1878ccff702Sbostic 	}
1888ccff702Sbostic 	if(play(brown, white, go))
1898ccff702Sbostic 		goto retry;
1908ccff702Sbostic 	if(piececount(brown, 0, 24) == 0){
1918ccff702Sbostic 		fprintf(stdout, "Brown wins");
1928ccff702Sbostic 		if(piececount(white, 0, 6) != 0)
1938ccff702Sbostic 			fprintf(stdout, " with a Backgammon.\n");
1948ccff702Sbostic 		else if(piececount(white, 0, 24) == 24)
1958ccff702Sbostic 			fprintf(stdout, " with a gammon.\n");
1968ccff702Sbostic 		else
1978ccff702Sbostic 			fprintf(stdout, ".\n");
1988ccff702Sbostic 		exit(0);
1998ccff702Sbostic 	}
2008ccff702Sbostic 	goto whitesmv;
2018ccff702Sbostic }
2028ccff702Sbostic 
play(player,playee,pos)2038ccff702Sbostic play(player,playee,pos)
2048ccff702Sbostic int *player,*playee,pos[];
2058ccff702Sbostic {
2068ccff702Sbostic 	int	k, n, die, ipos;
2078ccff702Sbostic 
2088ccff702Sbostic 	for(k=0; k < player[0]; k++){  /*blots on player[0] must be moved first*/
2098ccff702Sbostic 		if(pos[k] == NIL)
2108ccff702Sbostic 			break;
2118ccff702Sbostic 		if(pos[k] != 0){
2128ccff702Sbostic 			fprintf(stdout, "Stone on bar must be moved first.\n");
2138ccff702Sbostic 			return(NIL);
2148ccff702Sbostic 		}
2158ccff702Sbostic 	}
2168ccff702Sbostic 	for(k = 0; (ipos=pos[k]) != NIL; k++){
2178ccff702Sbostic 		die = k?die2:die1;
2188ccff702Sbostic 		n = 25-ipos-die;
2198ccff702Sbostic 		if(player[ipos] == 0)
2208ccff702Sbostic 			goto badmove;
2218ccff702Sbostic 		if(n > 0 && playee[n] >= 2)
2228ccff702Sbostic 			goto badmove;
2238ccff702Sbostic 		if(n <= 0){
2248ccff702Sbostic 			if(piececount(player,0,18) != 0)
2258ccff702Sbostic 				goto badmove;
2268ccff702Sbostic 			if((ipos+die) != 25 && piececount(player,19,24-die)!=0)
2278ccff702Sbostic 				goto badmove;
2288ccff702Sbostic 		}
2298ccff702Sbostic 		player[ipos]--;
2308ccff702Sbostic 		player[ipos+die]++;
2318ccff702Sbostic 	}
2328ccff702Sbostic 	for(k = 0; pos[k] != NIL; k++){
2338ccff702Sbostic 		die = k?die2:die1;
2348ccff702Sbostic 		n = 25-pos[k]-die;
2358ccff702Sbostic 		if(n>0 && playee[n]==1){
2368ccff702Sbostic 			playee[n]=0;
2378ccff702Sbostic 			playee[0]++;
2388ccff702Sbostic 		}
2398ccff702Sbostic 	}
2408ccff702Sbostic 	return(0);
2418ccff702Sbostic 
2428ccff702Sbostic badmove:
2438ccff702Sbostic 	fprintf(stdout, "Move %d illegal.\n", ipos);
2448ccff702Sbostic 	while(k--){
2458ccff702Sbostic 		die=k?die2:die1;
2468ccff702Sbostic 		player[pos[k]]++;
2478ccff702Sbostic 		player[pos[k]+die]--;
2488ccff702Sbostic 	}
2498ccff702Sbostic 	return(NIL);
2508ccff702Sbostic }
nextmove(player,playee)2518ccff702Sbostic nextmove(player,playee)
2528ccff702Sbostic int *player,*playee;
2538ccff702Sbostic {
2548ccff702Sbostic 	int	k;
2558ccff702Sbostic 
2568ccff702Sbostic 	imoves=0;
2578ccff702Sbostic 	movegen(player,playee);
2588ccff702Sbostic 	if(die1!=die2){
2598ccff702Sbostic 		k=die1;
2608ccff702Sbostic 		die1=die2;
2618ccff702Sbostic 		die2=k;
2628ccff702Sbostic 		movegen(player,playee);
2638ccff702Sbostic 	}
2648ccff702Sbostic 	if(imoves==0){
2658ccff702Sbostic 		fprintf(stdout, "no move possible.\n");
2668ccff702Sbostic 		return(NIL);
2678ccff702Sbostic 	}
2688ccff702Sbostic 	k=strategy(player,playee);		/*select kth possible move*/
2698ccff702Sbostic 	prtmov(k);
2708ccff702Sbostic 	update(player,playee,k);
2718ccff702Sbostic 	return(0);
2728ccff702Sbostic }
prtmov(k)2738ccff702Sbostic prtmov(k)
2748ccff702Sbostic int k;
2758ccff702Sbostic {
2768ccff702Sbostic 	int	n;
2778ccff702Sbostic 
2788ccff702Sbostic 	if(k == NIL)
2798ccff702Sbostic 		fprintf(stdout, "No move possible\n");
2808ccff702Sbostic 	else for(n = 0; n < 4; n++){
2818ccff702Sbostic 		if(moves[k].pos[n] == NIL)
2828ccff702Sbostic 			break;
2838ccff702Sbostic 		fprintf(stdout, "    %d, %d",25-moves[k].pos[n],moves[k].mov[n]);
2848ccff702Sbostic 	}
2858ccff702Sbostic 	fprintf(stdout, "\n");
2868ccff702Sbostic }
update(player,playee,k)2878ccff702Sbostic update(player,playee,k)
2888ccff702Sbostic int *player,*playee,k;
2898ccff702Sbostic {
2908ccff702Sbostic 	int	n,t;
2918ccff702Sbostic 
2928ccff702Sbostic 	for(n = 0; n < 4; n++){
2938ccff702Sbostic 		if(moves[k].pos[n] == NIL)
2948ccff702Sbostic 			break;
2958ccff702Sbostic 		player[moves[k].pos[n]]--;
2968ccff702Sbostic 		player[moves[k].pos[n]+moves[k].mov[n]]++;
2978ccff702Sbostic 		t=25-moves[k].pos[n]-moves[k].mov[n];
2988ccff702Sbostic 		if(t>0 && playee[t]==1){
2998ccff702Sbostic 			playee[0]++;
3008ccff702Sbostic 			playee[t]--;
3018ccff702Sbostic 		}
3028ccff702Sbostic 	}
3038ccff702Sbostic }
piececount(player,startrow,endrow)3048ccff702Sbostic piececount(player,startrow,endrow)
3058ccff702Sbostic int *player,startrow,endrow;
3068ccff702Sbostic {
3078ccff702Sbostic 	int	sum;
3088ccff702Sbostic 
3098ccff702Sbostic 	sum=0;
3108ccff702Sbostic 	while(startrow <= endrow)
3118ccff702Sbostic 		sum += player[startrow++];
3128ccff702Sbostic 	return(sum);
3138ccff702Sbostic }
pmoves()3148ccff702Sbostic pmoves()
3158ccff702Sbostic {
3168ccff702Sbostic 	int	i1, i2;
3178ccff702Sbostic 
3188ccff702Sbostic 	fprintf(stdout, "Possible moves are:\n");
3198ccff702Sbostic 	for(i1 = 0; i1 < imoves; i1++){
3208ccff702Sbostic 		fprintf(stdout, "\n%d",i1);
3218ccff702Sbostic 		 for (i2 = 0; i2<4; i2++){
3228ccff702Sbostic 			if(moves[i1].pos[i2] == NIL)
3238ccff702Sbostic 				break;
3248ccff702Sbostic 			fprintf(stdout, "%d, %d",moves[i1].pos[i2],moves[i1].mov[i2]);
3258ccff702Sbostic 		}
3268ccff702Sbostic 	}
3278ccff702Sbostic 	fprintf(stdout, "\n");
3288ccff702Sbostic }
3298ccff702Sbostic 
roll(who)3308ccff702Sbostic roll(who)
3318ccff702Sbostic {
3328ccff702Sbostic 	register n;
3338ccff702Sbostic 	char	 s[10];
3348ccff702Sbostic 
3358ccff702Sbostic 	if(who == BROWN && nobroll) {
3368ccff702Sbostic 		fprintf(stdout, "Roll? ");
3378ccff702Sbostic 		gets(s);
3388ccff702Sbostic 		n = sscanf(s, "%d%d", &die1, &die2);
3398ccff702Sbostic 		if(n != 2 || die1 < 1 || die1 > 6 || die2 < 1 || die2 > 6)
3408ccff702Sbostic 			fprintf(stdout, "Illegal - I'll do it!\n");
3418ccff702Sbostic 		else
3428ccff702Sbostic 			return;
3438ccff702Sbostic 	}
3448ccff702Sbostic 	die1 = ((rand()>>8) % 6) + 1;
3458ccff702Sbostic 	die2 = ((rand()>>8) % 6) + 1;
3468ccff702Sbostic }
3478ccff702Sbostic 
movegen(mover,movee)3488ccff702Sbostic movegen(mover,movee)
3498ccff702Sbostic int *mover,*movee;
3508ccff702Sbostic {
3518ccff702Sbostic 	int	k;
3528ccff702Sbostic 
3538ccff702Sbostic 	for(i = 0; i <= 24; i++){
3548ccff702Sbostic 		count = 0;
3558ccff702Sbostic 		if(mover[i] == 0)
3568ccff702Sbostic 			continue;
3578ccff702Sbostic 		if((k=25-i-die1) > 0 && movee[k] >= 2)
3588ccff702Sbostic 			if(mover[0] > 0)
3598ccff702Sbostic 				break;
3608ccff702Sbostic 		else
3618ccff702Sbostic 			continue;
3628ccff702Sbostic 		if(k <= 0){
3638ccff702Sbostic 			if(piececount(mover, 0, 18) != 0)
3648ccff702Sbostic 				break;
3658ccff702Sbostic 			if((i+die1) != 25 && piececount(mover,19,i-1) != 0)
3668ccff702Sbostic 				break;
3678ccff702Sbostic 		}
3688ccff702Sbostic 		mover[i]--;
3698ccff702Sbostic 		mover[i+die1]++;
3708ccff702Sbostic 		count = 1;
3718ccff702Sbostic 		for(j = 0; j <= 24; j++){
3728ccff702Sbostic 			if(mover[j]==0)
3738ccff702Sbostic 				continue;
3748ccff702Sbostic 			if((k=25-j-die2) > 0 && movee[k] >= 2)
3758ccff702Sbostic 				if(mover[0] > 0)
3768ccff702Sbostic 					break;
3778ccff702Sbostic 			else
3788ccff702Sbostic 				continue;
3798ccff702Sbostic 			if(k <= 0){
3808ccff702Sbostic 				if(piececount(mover,0,18) != 0)
3818ccff702Sbostic 					break;
3828ccff702Sbostic 				if((j+die2) != 25 && piececount(mover,19,j-1) != 0)
3838ccff702Sbostic 					break;
3848ccff702Sbostic 			}
3858ccff702Sbostic 			mover[j]--;
3868ccff702Sbostic 			mover[j+die2]++;
3878ccff702Sbostic 			count = 2;
3888ccff702Sbostic 			if(die1 != die2){
3898ccff702Sbostic 				moverecord(mover);
3908ccff702Sbostic 				if(mover[0] > 0)
3918ccff702Sbostic 					break;
3928ccff702Sbostic 				else
3938ccff702Sbostic 					continue;
3948ccff702Sbostic 			}
3958ccff702Sbostic 			for(l = 0; l <= 24; l++){
3968ccff702Sbostic 				if(mover[l] == 0)
3978ccff702Sbostic 					continue;
3988ccff702Sbostic 				if((k=25-l-die1) > 0 && movee[k] >= 2)
3998ccff702Sbostic 					if(mover[0] > 0)
4008ccff702Sbostic 						break;
4018ccff702Sbostic 				else
4028ccff702Sbostic 					continue;
4038ccff702Sbostic 				if(k <= 0){
4048ccff702Sbostic 					if(piececount(mover, 0, 18) != 0)
4058ccff702Sbostic 						break;
4068ccff702Sbostic 					if((l+die2) != 25 && piececount(mover,19,l-1) != 0)
4078ccff702Sbostic 						break;
4088ccff702Sbostic 				}
4098ccff702Sbostic 				mover[l]--;
4108ccff702Sbostic 				mover[l+die1]++;
4118ccff702Sbostic 				count=3;
4128ccff702Sbostic 				for(m=0;m<=24;m++){
4138ccff702Sbostic 					if(mover[m]==0)
4148ccff702Sbostic 						continue;
4158ccff702Sbostic 					if((k=25-m-die1) >= 0 && movee[k] >= 2)
4168ccff702Sbostic 						if(mover[0] > 0)
4178ccff702Sbostic 							break;
4188ccff702Sbostic 					else
4198ccff702Sbostic 						continue;
4208ccff702Sbostic 					if(k <= 0){
4218ccff702Sbostic 						if(piececount(mover,0,18) != 0)
4228ccff702Sbostic 							break;
4238ccff702Sbostic 						if((m+die2) != 25 && piececount(mover,19,m-1) != 0)
4248ccff702Sbostic 							break;
4258ccff702Sbostic 					}
4268ccff702Sbostic 					count=4;
4278ccff702Sbostic 					moverecord(mover);
4288ccff702Sbostic 					if(mover[0] > 0)
4298ccff702Sbostic 						break;
4308ccff702Sbostic 				}
4318ccff702Sbostic 				if(count == 3)
4328ccff702Sbostic 					moverecord(mover);
4338ccff702Sbostic 				else{
4348ccff702Sbostic 					mover[l]++;
4358ccff702Sbostic 					mover[l+die1]--;
4368ccff702Sbostic 				}
4378ccff702Sbostic 				if(mover[0] > 0)
4388ccff702Sbostic 					break;
4398ccff702Sbostic 			}
4408ccff702Sbostic 			if(count == 2)
4418ccff702Sbostic 				moverecord(mover);
4428ccff702Sbostic 			else{
4438ccff702Sbostic 				mover[j]++;
4448ccff702Sbostic 				mover[j+die1]--;
4458ccff702Sbostic 			}
4468ccff702Sbostic 			if(mover[0] > 0)
4478ccff702Sbostic 				break;
4488ccff702Sbostic 		}
4498ccff702Sbostic 		if(count == 1)
4508ccff702Sbostic 			moverecord(mover);
4518ccff702Sbostic 		else{
4528ccff702Sbostic 			mover[i]++;
4538ccff702Sbostic 			mover[i+die1]--;
4548ccff702Sbostic 		}
4558ccff702Sbostic 		if(mover[0] > 0)
4568ccff702Sbostic 			break;
4578ccff702Sbostic 	}
4588ccff702Sbostic }
moverecord(mover)4598ccff702Sbostic moverecord(mover)
4608ccff702Sbostic int *mover;
4618ccff702Sbostic {
4628ccff702Sbostic 	int	t;
4638ccff702Sbostic 
4648ccff702Sbostic 	if(imoves < MAXIMOVES) {
4658ccff702Sbostic 		for(t = 0; t <= 3; t++)
4668ccff702Sbostic 			moves[imoves].pos[t] = NIL;
4678ccff702Sbostic 		switch(count) {
4688ccff702Sbostic 		case 4:
4698ccff702Sbostic 			moves[imoves].pos[3]=m;
4708ccff702Sbostic 			moves[imoves].mov[3]=die1;
4718ccff702Sbostic 
4728ccff702Sbostic 		case 3:
4738ccff702Sbostic 			moves[imoves].pos[2]=l;
4748ccff702Sbostic 			moves[imoves].mov[2]=die1;
4758ccff702Sbostic 
4768ccff702Sbostic 		case 2:
4778ccff702Sbostic 			moves[imoves].pos[1]=j;
4788ccff702Sbostic 			moves[imoves].mov[1]=die2;
4798ccff702Sbostic 
4808ccff702Sbostic 		case 1:
4818ccff702Sbostic 			moves[imoves].pos[0]=i;
4828ccff702Sbostic 			moves[imoves].mov[0]=die1;
4838ccff702Sbostic 			imoves++;
4848ccff702Sbostic 		}
4858ccff702Sbostic 	}
4868ccff702Sbostic 	switch(count) {
4878ccff702Sbostic 	case 4:
4888ccff702Sbostic 		break;
4898ccff702Sbostic 
4908ccff702Sbostic 	case 3:
4918ccff702Sbostic 		mover[l]++;
4928ccff702Sbostic 		mover[l+die1]--;
4938ccff702Sbostic 		break;
4948ccff702Sbostic 
4958ccff702Sbostic 	case 2:
4968ccff702Sbostic 		mover[j]++;
4978ccff702Sbostic 		mover[j+die2]--;
4988ccff702Sbostic 		break;
4998ccff702Sbostic 
5008ccff702Sbostic 	case 1:
5018ccff702Sbostic 		mover[i]++;
5028ccff702Sbostic 		mover[i+die1]--;
5038ccff702Sbostic 	}
5048ccff702Sbostic }
5058ccff702Sbostic 
strategy(player,playee)5068ccff702Sbostic strategy(player,playee)
5078ccff702Sbostic int *player,*playee;
5088ccff702Sbostic {
5098ccff702Sbostic 	int	k, n, nn, bestval, moveval, prob;
5108ccff702Sbostic 
5118ccff702Sbostic 	n = 0;
5128ccff702Sbostic 	if(imoves == 0)
5138ccff702Sbostic 		return(NIL);
5148ccff702Sbostic 	goodmoves[0] = NIL;
5158ccff702Sbostic 	bestval = -32000;
5168ccff702Sbostic 	for(k = 0; k < imoves; k++){
5178ccff702Sbostic 		if((moveval=eval(player,playee,k,&prob)) < bestval)
5188ccff702Sbostic 			continue;
5198ccff702Sbostic 		if(moveval > bestval){
5208ccff702Sbostic 			bestval = moveval;
5218ccff702Sbostic 			n = 0;
5228ccff702Sbostic 		}
5238ccff702Sbostic 		if(n<MAXGMOV){
5248ccff702Sbostic 			goodmoves[n]=k;
5258ccff702Sbostic 			probmoves[n++]=prob;
5268ccff702Sbostic 		}
5278ccff702Sbostic 	}
5288ccff702Sbostic 	if(level=='e' && n>1){
5298ccff702Sbostic 		nn=n;
5308ccff702Sbostic 		n=0;
5318ccff702Sbostic 		prob=32000;
5328ccff702Sbostic 		for(k = 0; k < nn; k++){
5338ccff702Sbostic 			if((moveval=probmoves[k]) > prob)
5348ccff702Sbostic 				continue;
5358ccff702Sbostic 			if(moveval<prob){
5368ccff702Sbostic 				prob=moveval;
5378ccff702Sbostic 				n=0;
5388ccff702Sbostic 			}
5398ccff702Sbostic 			goodmoves[n]=goodmoves[k];
5408ccff702Sbostic 			probmoves[n++]=probmoves[k];
5418ccff702Sbostic 		}
5428ccff702Sbostic 	}
5438ccff702Sbostic 	return(goodmoves[(rand()>>4)%n]);
5448ccff702Sbostic }
5458ccff702Sbostic 
eval(player,playee,k,prob)5468ccff702Sbostic eval(player,playee,k,prob)
5478ccff702Sbostic int *player,*playee,k,*prob;
5488ccff702Sbostic {
5498ccff702Sbostic 	int	newtry[31], newother[31], *r, *q, *p, n, sum, first;
5508ccff702Sbostic 	int	ii, lastwhite, lastbrown;
5518ccff702Sbostic 
5528ccff702Sbostic 	*prob = sum = 0;
5538ccff702Sbostic 	r = player+25;
5548ccff702Sbostic 	p = newtry;
5558ccff702Sbostic 	q = newother;
5568ccff702Sbostic 	while(player<r){
5578ccff702Sbostic 		*p++= *player++;
5588ccff702Sbostic 		*q++= *playee++;
5598ccff702Sbostic 	}
5608ccff702Sbostic 	q=newtry+31;
5618ccff702Sbostic 	for(p = newtry+25; p < q; p++)		/* zero out spaces for hit pieces */
5628ccff702Sbostic 		*p = 0;
5638ccff702Sbostic 	for(n = 0; n < 4; n++){
5648ccff702Sbostic 		if(moves[k].pos[n] == NIL)
5658ccff702Sbostic 			break;
5668ccff702Sbostic 		newtry[moves[k].pos[n]]--;
5678ccff702Sbostic 		newtry[ii=moves[k].pos[n]+moves[k].mov[n]]++;
5688ccff702Sbostic 		if(ii<25 && newother[25-ii]==1){
5698ccff702Sbostic 			newother[25-ii]=0;
5708ccff702Sbostic 			newother[0]++;
5718ccff702Sbostic 			if(ii<=15 && level=='e')		/* hit if near other's home */
5728ccff702Sbostic 				sum++;
5738ccff702Sbostic 		}
5748ccff702Sbostic 	}
5758ccff702Sbostic 	for(lastbrown = 0; newother[lastbrown] == 0; lastbrown++);
5768ccff702Sbostic 		;
5778ccff702Sbostic 	for(lastwhite = 0; newtry[lastwhite] == 0; lastwhite++)
5788ccff702Sbostic 		;
5798ccff702Sbostic 	lastwhite = 25-lastwhite;
5808ccff702Sbostic 	if(lastwhite<=6 && lastwhite<lastbrown)
5818ccff702Sbostic 		sum=1000;
5828ccff702Sbostic 									/* experts running game. */
5838ccff702Sbostic 									/* first priority is to */
5848ccff702Sbostic 									/* get all pieces into */
5858ccff702Sbostic 									/* white's home */
5868ccff702Sbostic 	if(lastwhite<lastbrown && level=='e' && lastwhite>6) {
5878ccff702Sbostic 		for(sum = 1000; lastwhite > 6; lastwhite--)
5888ccff702Sbostic 			sum = sum-lastwhite*newtry[25-lastwhite];
5898ccff702Sbostic 	}
5908ccff702Sbostic 	for(first = 0; first < 25; first++)
5918ccff702Sbostic 		if(newother[first] != 0)		/*find other's first piece*/
5928ccff702Sbostic 			break;
5938ccff702Sbostic 	q = newtry+25;
5948ccff702Sbostic 	for(p = newtry+1; p < q;)			/* blocked points are good */
5958ccff702Sbostic 		if(*p++ > 1)
5968ccff702Sbostic 			sum++;
5978ccff702Sbostic 	if(first > 5) {					/* only stress removing pieces if */
5988ccff702Sbostic 							/* homeboard cannot be hit */
5998ccff702Sbostic 		q = newtry+31;
6008ccff702Sbostic 		p=newtry+25;
6018ccff702Sbostic 		for(n = 6; p < q; n--)
6028ccff702Sbostic 			sum += *p++ * n;			/*remove pieces, but just barely*/
6038ccff702Sbostic 	}
6048ccff702Sbostic 	if(level != 'b'){
6058ccff702Sbostic 		r = newtry+25-first;	/*singles past this point can't be hit*/
6068ccff702Sbostic 		for(p = newtry+7; p < r; )
6078ccff702Sbostic 			if(*p++ == 1)		/*singles are bad after 1st 6 points if they can be hit*/
6088ccff702Sbostic 				sum--;
6098ccff702Sbostic 		q = newtry+3;
6108ccff702Sbostic 		for(p = newtry; p < q; )	   /*bad to be on 1st three points*/
6118ccff702Sbostic 			sum -= *p++;
6128ccff702Sbostic 	}
6138ccff702Sbostic 
6148ccff702Sbostic 	for(n = 1; n <= 4; n++)
6158ccff702Sbostic 		*prob += n*getprob(newtry,newother,6*n-5,6*n);
6168ccff702Sbostic 	return(sum);
6178ccff702Sbostic }
instructions()6188ccff702Sbostic instructions()
6198ccff702Sbostic {
6208ccff702Sbostic 	register fd, r;
6218ccff702Sbostic 	char	 buf[BUFSIZ];
6228ccff702Sbostic 
6238ccff702Sbostic 	if((fd = open(RULES, 0)) < 0) {
6248ccff702Sbostic 		fprintf(stderr, "back: cannot open %s\n", RULES);
6258ccff702Sbostic 		return;
6268ccff702Sbostic 	}
6278ccff702Sbostic 	while(r = read(fd, buf, BUFSIZ))
6288ccff702Sbostic 		write(1, buf, r);
6298ccff702Sbostic }
6308ccff702Sbostic 
getprob(player,playee,start,finish)6318ccff702Sbostic getprob(player,playee,start,finish)
6328ccff702Sbostic int *player,*playee,start,finish;
6338ccff702Sbostic {			/*returns the probability (times 102) that any
6348ccff702Sbostic 			  pieces belonging to 'player' and lying between
6358ccff702Sbostic 			  his points 'start' and 'finish' will be hit
6368ccff702Sbostic 			  by a piece belonging to playee
6378ccff702Sbostic 			*/
6388ccff702Sbostic 	int	k, n, sum;
6398ccff702Sbostic 
6408ccff702Sbostic 	sum = 0;
6418ccff702Sbostic 	for(; start <= finish; start++){
6428ccff702Sbostic 		if(player[start] == 1){
6438ccff702Sbostic 			for(k = 1; k <= 12; k++){
6448ccff702Sbostic 				if((n=25-start-k) < 0)
6458ccff702Sbostic 					break;
6468ccff702Sbostic 				if(playee[n] != 0)
6478ccff702Sbostic 					sum += probability[k];
6488ccff702Sbostic 			}
6498ccff702Sbostic 		}
6508ccff702Sbostic 	}
6518ccff702Sbostic 	return(sum);
6528ccff702Sbostic }
prtbrd()6538ccff702Sbostic prtbrd()
6548ccff702Sbostic {
6558ccff702Sbostic 	int	k;
6568ccff702Sbostic 	static char undersc[]="______________________________________________________";
6578ccff702Sbostic 
6588ccff702Sbostic 	fprintf(stdout, "White's Home\n%s\r",undersc);
6598ccff702Sbostic 	for(k = 1; k <= 6; k++)
6608ccff702Sbostic 		fprintf(stdout, "%4d",k);
6618ccff702Sbostic 	fprintf(stdout, "    ");
6628ccff702Sbostic 	for(k = 7; k <= 12; k++)
6638ccff702Sbostic 		fprintf(stdout, "%4d",k);
6648ccff702Sbostic 	putchar('\n');
6658ccff702Sbostic 	numline(brown, white, 1, 6);
6668ccff702Sbostic 	fprintf(stdout, "    ");
6678ccff702Sbostic 	numline(brown, white, 7, 12);
6688ccff702Sbostic 	putchar('\n');
6698ccff702Sbostic 	colorline(brown, 'B', white, 'W', 1, 6);
6708ccff702Sbostic 	fprintf(stdout, "    ");
6718ccff702Sbostic 	colorline(brown, 'B', white, 'W', 7, 12);
6728ccff702Sbostic 	putchar('\n');
6738ccff702Sbostic 	if(white[0] != 0)
6748ccff702Sbostic 		fprintf(stdout, "%28dW\n",white[0]);
6758ccff702Sbostic 	else
6768ccff702Sbostic 		putchar('\n');
6778ccff702Sbostic 	if(brown[0] != 0)
6788ccff702Sbostic 		fprintf(stdout, "%28dB\n", brown[0]);
6798ccff702Sbostic 	else
6808ccff702Sbostic 		putchar('\n');
6818ccff702Sbostic 	colorline(white, 'W', brown, 'B', 1, 6);
6828ccff702Sbostic 	fprintf(stdout, "    ");
6838ccff702Sbostic 	colorline(white, 'W', brown, 'B', 7, 12);
6848ccff702Sbostic 	fprintf(stdout, "\n%s\r",undersc);
6858ccff702Sbostic 	numline(white, brown, 1, 6);
6868ccff702Sbostic 	fprintf(stdout, "    ");
6878ccff702Sbostic 	numline(white, brown, 7, 12);
6888ccff702Sbostic 	putchar('\n');
6898ccff702Sbostic 	for(k = 24; k >= 19; k--)
6908ccff702Sbostic 		fprintf(stdout, "%4d",k);
6918ccff702Sbostic 	fprintf(stdout, "    ");
6928ccff702Sbostic 	for(k = 18; k >= 13; k--)
6938ccff702Sbostic 		fprintf(stdout, "%4d",k);
6948ccff702Sbostic 	fprintf(stdout, "\nBrown's Home\n\n\n\n\n");
6958ccff702Sbostic }
numline(upcol,downcol,start,fin)6968ccff702Sbostic numline(upcol,downcol,start,fin)
6978ccff702Sbostic int *upcol,*downcol,start,fin;
6988ccff702Sbostic {
6998ccff702Sbostic 	int	k, n;
7008ccff702Sbostic 
7018ccff702Sbostic 	for(k = start; k <= fin; k++){
7028ccff702Sbostic 		if((n = upcol[k]) != 0 || (n = downcol[25-k]) != 0)
7038ccff702Sbostic 			fprintf(stdout, "%4d", n);
7048ccff702Sbostic 		else
7058ccff702Sbostic 			fprintf(stdout, "    ");
7068ccff702Sbostic 	}
7078ccff702Sbostic }
colorline(upcol,c1,downcol,c2,start,fin)7088ccff702Sbostic colorline(upcol,c1,downcol,c2,start,fin)
7098ccff702Sbostic int *upcol,*downcol,start,fin;
7108ccff702Sbostic char c1,c2;
7118ccff702Sbostic {
7128ccff702Sbostic 	int	k;
7138ccff702Sbostic 	char 	c;
7148ccff702Sbostic 
7158ccff702Sbostic 	for(k = start; k <= fin; k++){
7168ccff702Sbostic 		c = ' ';
7178ccff702Sbostic 		if(upcol[k] != 0)
7188ccff702Sbostic 			c = c1;
7198ccff702Sbostic 		if(downcol[25-k] != 0)
7208ccff702Sbostic 			c = c2;
7218ccff702Sbostic 		fprintf(stdout, "   %c",c);
7228ccff702Sbostic 	}
7238ccff702Sbostic }
724