home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
240_01
/
bg3.c
< prev
next >
Wrap
Text File
|
1987-07-31
|
26KB
|
840 lines
/*
** bg3.c -- gameplan
*/
#include "backgmmn.h"
/*=============================================*/
/* M Y M O V E */
/*=============================================*/
static naked() { /* am I leaving too many blots? */
static int i, clink;
i = 24; clink = 0;
while (i) {
if (point[i].stones == 1 && point[i].owner == ME) clink++;
i--;
}
return (clink > 2);
} /* end: naked */
static yourfolly() { /* look for lotsa blots in your inner table */
static int i, clink;
i = 18; clink = 0;
while (i < 25) {
if (point[i].owner == YU && point[i].stones == 1)
clink++;
i++;
}
return (clink >= 3);
} /* end: yourfolly */
static goodboard() { /* look for four made points near my inner table */
static int i, clank, clink;
i = 9; clank = 0;
while (i > 3) {
if (point[i].owner == ME && point[i].stones > 1) clank++;
i--;
}
if (clank > 4) return (TRUE); /* bar is nearly blocked */
i = 6; clank = clink = 0;
while (i) {
if (point[i].owner != ME)
;
else if (point[i].stones == 1) clink++; else clank++;
i--;
}
return (clank > 3 && clink < 2);
} /* end: goodboard */
static scanahead( from ) int from; {
static int count;
count = 0;
while (--from > 0) {
++count;
if ( point[ from ].owner == YU ) return (count);
}
return (7);
} /* end: scanahead */
/*------------------------------------------------------------*/
/* MATCHUP */
/* */
/* 2-stone functions that force the choice of the next move. */
/* These are the HEART and SOUL of this backgammon algorithm! */
/*------------------------------------------------------------*/
static setpend( from, to ) int from, to; {
pending.fr = from;
pending.to = to;
pending.flag = TRUE;
} /* end: setpend */
static natural(f1,t1,f2,t2) int f1,t1,f2,t2; {
clrpend();
if (point[t2].stones == 1 && t1 == f2) setpend(f2,t2);
return (pending.flag);
} /* end: natural */
static matchup( test4 ) int (* test4)(); {
static int i, j, ti, tj;
if ( pending.flag ) return (FALSE); /* this is probably redundant */
for (i = 1; i < 26; i++) {
ti = list[0][i];
if ( ti == ERROR ) goto zoo;
for (j = 1; j < 26; j++) {
tj = list[1][j];
if ( tj == ERROR ) goto voo;
if ( (* test4)( i, ti, j, tj ) ) {
lurch( i, ti, 0);
return (TRUE);
}
voo: ;
}
zoo: ;
}
return (FALSE);
} /* end: matchup */
static matchhi( test4 ) int (* test4)(); {
static int i, j, ti, tj;
if ( pending.flag ) return (FALSE); /* this is probably redundant */
for (i = 1; i < 26; i++) {
ti = list[1][i];
if ( ti == ERROR ) goto zoo;
for (j = 1; j < 26; j++) {
tj = list[0][j];
if ( tj == ERROR ) goto voo;
if ( (* test4)( i, ti, j, tj ) ) {
lurch( i, ti, 1);
return (TRUE);
}
voo: ;
}
zoo: ;
}
return (FALSE);
} /* end: matchhi */
/*--------------------------------------------------------*/
/* CLOCKWISE and COUNTERCLOCK */
/* */
/* the rest of these are single-stone decisions based on */
/* rules of thumb, board-scanning functions */
/*--------------------------------------------------------*/
static plainstupid( from ) int from; { /* don't break a safe point */
return (from < 13 && (point[from].stones == 2 && scanahead(from) < 7));
} /* end: plainstupid */
static unwise( innertablept ) int innertablept; {
/* if it's a hit, just for god's sake don't put him on the bar!! */
if ( innertablept < 7 ) {
if (point[ innertablept ].owner == YU ||
point[ YRBAR ].stones > 0)
return (TRUE);
}
return(FALSE);
} /* end: unwise */
static covermine( from, to ) int from, to; {
if ( from < 8 ) return(FALSE);
return ( (point[ to ].stones == 1) && (point[ to ].owner == ME) );
} /* end: covermine */
static idareyou( from, to ) int from, to; {
if (unwise( to )) return (FALSE);
if ( (point[ from ].stones != 2)
&& (point[ to ].stones < 2)
&& (scanahead( to ) > 6) ) return ( TRUE );
else return (FALSE);
} /* end: idareyou */
static hitandrun( from, to ) int from, to; {
return ( point[ to ].owner == YU );
} /* end: hitandrun */
static dbuild( from, to ) int from, to; {
static int diceleft;
diceleft = (myturns? 2 + movesleft: movesleft);
if (diceleft > 1) {
/* can't possibly be only one stone on from point */
/* or kamikaze would have covered it on last move */
return ( point[to].stones == 0 );
}
return (FALSE);
} /* end: dbuild */
static kamikaze( from, to ) int from, to; {
/* cover my distant blot, or razzle-dazzle 'em with the long doubles hit */
static int j, k, diceleft;
k = from;
j = from - to;
diceleft = myturns * movesleft; /* NB: 2*2 == 2+2, "fourtunately" */
while ( diceleft-- ) { /* predicting where doubles land is easy! */
k -= j;
if (k < 1) return (FALSE); /* out of bounds */
if ( point[ k ].stones == 0 ) continue; /* simplify */
if ( point[ k ].stones == 1 ) /* found my blot or yours? */
return (TRUE);
else if ( point[k].owner == YU ) /* found your blockade? */
return (FALSE);
else continue; /* found my safe point, so ignore it */
}
return (FALSE);
} /* end: kamikaze */
static hittite( from, to ) int from, to; {
return (hitandrun(from,to) && to > 9);
} /* end: hittite */
static safehit( from, to ) int from, to; {
return (hittite(from,to) && idareyou(from,to));
} /* end: safehit */
static foolsdemise( from, to ) int from, to; {
/* annihilate orphaned blots in enemy's inner, my outer table */
return (to > 17 && point[to].owner == YU);
} /* end: foolsdemise */
static landonme( from, to ) int from, to; {
if ( plainstupid(from) ) return (FALSE);
if ( loneranger(from,to) ) {
if (from < 19 && to > 6) return(TRUE);
}
else return ( point[ to ].owner == ME && point[to].stones < 4);
} /* end: landonme */
/* these evaluations have meaning only in the endgame */
static nobackgammon( from, to ) int from, to; { /* endgame */
return (from > 19);
} /* end: nobackgammon */
static crosstable( from, to ) int from, to; {
/* always move a table ahead if possible, in the endgame */
if (from < 7) return (FALSE);
if (from > 18 && to <= 18) return (TRUE);
if (from > 12 && to <= 12) return (TRUE);
if (from > 6 && to <= 6) return (TRUE);
return (FALSE);
} /* end: crosstable */
static fiftytworule( from, to ) int from, to; { /* endgame */
static int p;
if (from < 7) return (FALSE); /* not in inner table! */
p = from % 6;
if (p == 0) return (TRUE); /* improve the six */
if (p != 5) return ( (to % 6) < 3 ); /* best improve under five */
} /* end: fiftytworule */
/* these evaluations are universally applicable, last resort moves */
static gohome( from, to ) int from, to; { /* always go home if you can */
return (to == MYHOME);
} /* end: gohome */
static scatter( from, to ) int from, to; { /* scatter, esp. in the endgame */
if (plainstupid(from) || unwise(to)) return (FALSE);
return