|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 23993 (0x5db9)
Types: TextFile
Names: »dam.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Draughts/dam.c«
/* Copyright (C) A.E. Brouwer, Amsterdam, 1977,1985 */
/* Interactive draugths playing program */
/* Version 1.0, AEB, Easter monday 1977 */
/* Version 2.0, AEB&CLP, 770514 */
/* Version 3.0, AEB&CLP, 771203 */
/* Linted and converted to BSD4.2, AEB, 850725 */
#include <setjmp.h>
#include <signal.h>
#include "damdefs.h"
#define MSIZE 3000
#define GSIZE 1000
/*
Numbering of the board:
00 01 02 03 04 05
05 06 07 08 09 10
11 12 13 14 15 16
16 17 18 19 20 21
22 23 24 25 26 27
27 28 29 30 31 32
33 34 35 36 37 38
38 39 40 41 42 43
44 45 46 47 48 49
49 50 51 52 53 54
55 56 57 58 59 60
60 61 62 63 64 65
where the fields 0-5, 16, 27, 38, 49, 60-65
constitute the edge of the board.
Note: the fields with numbers divisible by 5
form the main diagonal (see 'value(c)').
Conversion tables:
*/
int conv[51] = { 0,
6, 7, 8, 9,10,
11,12,13,14,15,
17,18,19,20,21,
22,23,24,25,26,
28,29,30,31,32,
33,34,35,36,37,
39,40,41,42,43,
44,45,46,47,48,
50,51,52,53,54,
55,56,57,58,59
};
int reconv[66] = {
0, 0, 0, 0, 0, 0,
1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 0,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 0,
21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 0,
31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 0,
41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 0,
0, 0, 0, 0, 0
};
int bord[66];
int game[GSIZE];
int *gp = &game[0];
int moves[MSIZE];
int playb,playw;
int mvnr = 1; /* odd means black's move */
int endgame = 0; /* endgame strategy */
int fouragnst1 = 0; /* four kings against one */
int lasthap = 1; /* draw if nothing happens for too long */
int drawdel = DRAWWT; /* 3 or 10 or DRAWWT */
int me = WHITE; /* player to move */
int optp = 1; /* frequency of prbord() */
int optg = 0; /* nonzero if game */
int optu = 0; /* print evaluation */
/* bit0: static evaluation of position
bit1: static evaluation of each move
bit2: evaluation of position
bit3: evaluation of each move
*/
int optf = -1; /* file descriptor of ofile */
int userand = 1;
int rdif = 100; /* cannot be much larger */
int rdifmin = 100; /* min used during this game */
int rdmin = 1; /* minimum recursion depth */
int rdmax = 10; /* maximum recursion depth */
int fplevel = 1; /* level of search for free paths */
int captct,captmax, *mpf,*mp0,*mp,possct;
extern int *findmove(), *readmove();
extern long lseek();
int debug,crownmv,altermv;
int rescct;
int wpct,bpct,wkct,bkct; /* global */
int timeb,timew; /* time used by b/w (in seconds) */
int timemax = 10; /* nr of seconds allowed per move */
extern int value2(),value(),evalue();
int (*avalue)() = value;
int (*stratw)(),(*stratb)();
int (*(strategies[]))() = { value, value2, evalue };
extern int pb,disp,dirt,prall,prbwait;
extern char line[];
extern int rdbord[];
setstrat(w,b) int w,b; {
register int i;
i = sizeof(strategies)/2;
if(w >= i || b >= i){
pmesg("no such strategies\n");
return;
}
stratw = strategies[w];
stratb = strategies[b];
pmesg("strategies %d(w),%d(b)\n",w,b);
}
intrup(){
(void) signal(SIGINT,SIG_IGN); /* no more interrupts */
if(disp) delay();
pmesg("?");
rdlin();
rdcomd(line);
(void) signal(SIGINT,intrup);
if(!mpf){
pmesg("you cannot change the board during an interrupt\n");
reset();
}
}
int intflg = 0; /* interrupt while non-interruptable */
intrdp(){
intflg++;
(void) signal(SIGINT,intrdp);
}
jmp_buf env;
main(argc,argv)
int argc;
char **argv;
{
int p;
char *ac;
initterm();
printf("dam %s version %s\n",VERSION,DATE);
optf = open(".outdam",1); /* use it if it exists */
if(optf >= 0) (void) lseek(optf, 0L, 2); /* seek eof */
setstrat(0,1);
if(argc == 1){
printf("do you want info? (y/n)\n");
if(answer()) prinfo();
}
if(signal(SIGINT, SIG_IGN) != SIG_IGN)
(void) signal(SIGINT, intrup);
if(setjmp(env)) ; /* Program was reset */
if(mvnr > 1){
prbord();
rdcomd("t"); /* report time used */
if(optf > 0) outgame();
printf("another game?\n");
if(!answer()) exit(0);
}
sleep(2);
init();
/* 2nd time here argc will be one */
while(--argc) {
ac = *++argv;
if(*ac == '-') ac++;
switch(*ac){
case 'p':
optp = atoi(++ac);
break;
case 'g':
optg++;
break;
case ':':
debug++;
break;
case '\0':
/* do not use random generator */
userand = 0;
printf("no random generator used\n");
break;
default:
rdcomd(ac);
}
}
argc++;
init2();
while(1){
mvnr++;
if(optu&3) prsteval();
timebeg();
p = ((me == WHITE) ? playw : playb);
if(p == USER) domove(readmove(me));
else domove(findmove(me));
if(me == WHITE) timew += timedif();
else timeb += timedif();
if(optp) if(mvnr%optp == 0) prbord();
me = COL-me;
}
}
reset(){
longjmp(env,1);
}
init(){
register int i;
/* check correctness of conv and reconv */
for(i=1; i<=50; i++)
if(reconv[conv[i]] != i)
error("conv error");
/* fill edge of the board */
for(i=0; i<66; i++)
if(reconv[i] == 0) bord[i] = EDGE;
/* initial board position */
for(i=1; i<=20; i++)
bord[conv[i]] = BLACK;
for(i=21; i<=30; i++)
bord[conv[i]] = EMPTY;
for(i=31; i<=50; i++)
bord[conv[i]] = WHITE;
me = WHITE; /* white to move */
rdbord[0] = 0; /* not from file */
timew = timeb = 0;
lasthap = mvnr =1;
endgame = fouragnst1 = 0;
crownmv = altermv = 0;
mpf = &moves[0];
gp = &game[0];
prall++;
}
init2(){
if(!playb && !playw){
printf("do you want me to play black? (y/n)\n");
playb = answer()+1;
printf("do you want me to play white? (y/n)\n");
playw = answer()+1;
dirt++;
} else {
if(!playb) playb = USER;
if(!playw) playw = USER;
}
if(!mpf) mpf = moves; else
if(optp)prbord();
}
/* fatal error routine */
error(s) char *s; {
printf("%s\n",s);
exit(0);
}
/* create list of all possible moves */
move(c) int c; {
register int i;
int c0;
possct = 0;
captmax = captct = 0;
mp = mp0 = mpf;
for(i=6; i<60; i++) if(((c0 = bord[i]) & COL) == c) {
bord[i] = EMPTY;
mp += 3;
*mp0 = i+c0;
capt(c0,i);
mp -= 3;
bord[i] = c0;
}
if(!captmax) {
if(c == BLACK) {
for(i=6; i<60; i++) if(((c0 = bord[i]) & COL) == c) {
if(c0 == BLACK) {
hmove(c0,i,5);
hmove(c0,i,6);
} else {
dmove(c0,i,-6);
dmove(c0,i,-5);
dmove(c0,i,5);
dmove(c0,i,6);
}
}} else
for(i=59; i>5; i--) if(((c0 = bord[i]) & COL) == c) {
if(c0 == WHITE) {
hmove(c0,i,-5);
hmove(c0,i,-6);
} else {
dmove(c0,i,-6);
dmove(c0,i,-5);
dmove(c0,i,5);
dmove(c0,i,6);
}
}
}
if(mp > &moves[MSIZE]) error("overflow moves array");
}
/* king move in specified direction */
dmove(c,pos,dir) int c,pos,dir; {
register int i;
for(i = pos+dir; bord[i] == EMPTY; i += dir){
*mp++ = pos+c;
*mp++ = i+c;
*mp++ = 0;
possct++;
}
}
/* piece move */
hmove(c,pos,dir) int c,pos,dir; {
register int i;
if(bord[i = pos+dir] == EMPTY){
*mp++ = pos + c;
*mp++ = prom(c,i);
*mp++ = 0;
possct++;
}
}
/* partial capture in specified direction */
hcapt(c,pos,dir) int c,pos,dir; {
register int i,j;
int c1;
if(c&DAM){
for(i=pos+dir; (c1=bord[i]) == EMPTY; i += dir);
if((c1 & MASK) != DAM+COL-c) return;
j = i;
bord[i] |= CAPT;
captct++;
*mp++ = i+c1;
while(bord[j += dir] == EMPTY)
capt(c,j);
bord[i] = c1;
captct--;
mp--;
} else {
c1 = bord[i = pos+dir];
if((c1 & MASK) != COL-c) return;
if(bord[j=i+dir] != EMPTY) return;
bord[i] |= CAPT;
captct++;
*mp++ = i+c1;
capt(c,j);
bord[i] = c1;
captct--;
mp--;
}
}
capt(c,pos) int c,pos; {
register int *mp1;
hcapt(c,pos,-6);
hcapt(c,pos,-5);
hcapt(c,pos,5);
hcapt(c,pos,6);
if(captct == captmax){
if(!captct) return;
possct++;
*++mp0 = prom(c,pos);
*++mp0 = captct;
mp0 -= 2;
mp1 = mp;
do { *mp++ = *mp0++; } while (mp0 != mp1);
return;
} else if(captct > captmax){
captmax = captct;
possct = 1;
mp1 = mpf;
*mp1++ = *mp0;
*mp1++ = prom(c,pos);
*mp1++ = captct;
mp0 += 3;
do { *mp1++ = *mp0++; } while(mp0 != mp);
mp0 = mpf;
mp = mp1;
do { *mp1++ = *mp0++; } while(mp0 != mp);
mp = mp1;
return;
}
}
prom(c,pos) int c,pos; {
if(c&WHITE) {
if(pos < 11) c |= DAM;
} else if(pos > 54) c |= DAM;
return(pos+c);
}
/* execute actual move */
domove(mvpt) int *mvpt; {
register int i;
register int *mp1;
int ct,ctd,cte;
int difflist[66];
/* store move in array game */
mp1 = mvpt;
*gp++ = *mp1++;
*gp++ = *mp1++;
*gp++ = ct = *mp1++;
while(ct--) *gp++ = *mp1++;
if(gp+4 > &game[GSIZE]) error("overflow game array");
/* change board position */
mp1 = mvpt;
bord[((*mp1++) & 0377)] = EMPTY;
i = *mp1 & VAL;
bord[((*mp1++) & 0377)] = i;
ct = *mp1++;
if(ct || !(*mvpt & DAM)) lasthap = mvnr;
while(ct--) bord[((*mp1++) & 0377)] = EMPTY;
/* check for repetition of moves */
ct = cte = 0;
ctd = mvnr-lasthap;
if(ctd > 3){
for(i=0; i<66; i++) difflist[i]=0;
mp1 = gp;
while(ctd--){ /* go back one move */
if(*--mp1) error("capture after lasthap");
i = *--mp1;
if(i & (difflist[i & 0377] ^= (i&COL)))
ct++;
else ct--;
i = *--mp1;
if(i & (difflist[i & 0377] ^= (i&COL)))
ct++;
else ct--;
if(difflist[0] ^= 1) ct++;
else ct--;
if(!ct) cte++;
}
if(cte == 2){
pmesg("\nDraw by repetition of moves\n");
reset();
} else if(cte == 1) {
pmesg("\nThis is the 2nd occurrence\
of this position\n");
pb = 1;
}
}
/* check for three kings against one */
pdistr();
if((!wpct) && (!bpct) && (wkct+bkct == 4) && ((wkct&bkct) == 1)){
drawdel = 10;
ct = (wkct==1 ? WHITE : BLACK);
/* single king on main diagonal? */
for(i=10; i<60; i += 5)
if(bord[i] & ct){
drawdel = 3;
break;
}
}
if(mvnr-lasthap > drawdel*2){
pmesg("\nDraw since nothing happened for %d moves\n",
drawdel);
reset();
}
if(wkct+bkct && wpct+bpct<12) {
if(!endgame) setstrat(2,2); /* %% */
endgame++;
}
if(endgame && ((wkct > 3) && (bkct < 2) ||
(bkct > 3) && (wkct < 2)))
fouragnst1++;
}
/* he asks for remise, shall we accept it? */
/* very stupid algorithm %% */
remise(){
if(mvnr-lasthap > drawdel*2){
pmesg("I accept\n");
reset();
} else {
pmesg("I reject\n");
}
}
pdistr(){ /* find distribution of white and black pieces */
register int i;
wpct = wkct = bpct = bkct = 0;
for(i=6; i<60; i++) switch(bord[i] & VAL){
case WHITE:
wpct++;
break;
case BLACK:
bpct++;
break;
case WHITE|DAM:
wkct++;
break;
case BLACK|DAM:
bkct++;
break;
default:
break;
}
}
crown(c) int c; {
register int i,v;
int pct,kct,kseen,save_i[2],sk;
pct = kct = kseen = 0;
for(i=1; i<=50; i++){
v = bord[conv[i]] & VAL;
if(v == EMPTY) continue;
if(v & c){
if(kseen++ || (!(v & DAM))) goto err;
else sk = i;
} else {
if(v & DAM) kct++;
else if(pct == 2) goto err;
else save_i[pct++] = i;
}
}
if((kct + pct == 3) && pct){
drawdel = ((sk/5)*5 == sk ? 3 : 10);
lasthap = crownmv = mvnr;
pmesg("%d pieces crowned to king\n",pct);
pmesg("it will be a draw in %d moves\n",drawdel);
while(pct--){
bord[conv[save_i[pct]]] |= DAM;
}
} else {
err:
pmesg("crowning my pieces to a king is allowed only\n");
pmesg("if I have 3 pieces among which 1 or 2 kings\n");
}
}
int rdepth;
int res0,res1,res2;
/* allowed difference with optimal move */
#define Q 30
int*
findmove(c) int c; {
int r,res;
struct mvv {
int *mvp,val0,val1;
} mvvals[MVMAX], *mvg;
register struct mvv *mvvp;
register int *mp1;
rescct = 0;
move(c);
if(!possct){
pmesg("I lost\n");
reset();
}
if(possct == 1){
prmove(mpf);
return(mpf);
}
avalue = (me == WHITE ? stratw : stratb);
rdepth = 0;
res2 = -1;
/* first look to a short depth */
rdif -= 40;
rdmin--;
res = -GIANT;
mvvp = mvvals;
for(mp1 = mpf; mp1<mp; ){
r = result(mp1,res-Q,GIANT);
if(r < -GIANT) r = -GIANT;
if(r > res) res = r;
mvvp->mvp = mp1;
mvvp++->val0 = r;
if(mvvp >= mvvals+MVMAX-1){
pmesg("error in findmove: MVMAX too small\n");
break;
}
mp1 += 2;
mp1 += (*mp1++);
}
/* end of list */
mvvp->mvp = 0;
/* sort mvvals */
for(mvvp=mvvals; mp1=(mvvp+1)->mvp; mvvp++){
res1 = (mvvp+1)->val0;
test:
if(res1 > (res0 = mvvp->val0)){
/* switch */
(mvvp+1)->mvp = mvvp->mvp;
(mvvp+1)->val0 = res0;
mvvp -> mvp = mp1;
mvvp -> val0 = res1;
if(mvvp > mvvals){
mvvp--;
goto test;
}
}
}
/* short term result */
res0 = res;
/* now look to full depth */
mvvp = mvvals;
rdif += 40;
rdmin++;
res = -GIANT-1; /* force assignment to mvg */
while(mp1 = mvvp->mvp){
r = result(mp1,res-Q,GIANT);
if(r < -GIANT) r = -GIANT;
if(r > res){
res = r;
mvg = mvvp;
/* gdct = 1; */
}
/* else if(r == res)if(random(++gdct)==0) mvg=mvvp; %% */
mvvp++ -> val1 = r;
}
/* long term result */
res1 = res;
/* final result good? */
if(res1 >= res0-Q) goto ret;
/* or short term result not worse than for the others? */
if(mvg->val0 >= res0-30) goto ret;
/* this seems a bad move at first sight;
see whether it is really necessary */
rdif += (mp-mpf);
res2 = result(mvg->mvp, res1-PVAL, res1+PVAL);
rdif -= (mp-mpf);
if(res2 >= res1-Q) goto ret;
/* a bad move after all, take the one that seems best */
r = -GIANT-1;
mvvp = mvvals;
while(mvvp->val0 >= res0-Q){
if(mvvp->val1 > r){
r = mvvp->val1;
mvg = mvvp;
}
mvvp++;
}
ret:
if(optu&8){
disp = 0;
/* print value of each move */
mvvp = mvvals;
while(mp1 = mvvp->mvp){
prmove(mp1);
printf(mvvp == mvg ? "####" : "****");
printf(" %d %d\n",mvvp->val0,mvvp->val1);
mvvp++;
}
putchar('\n');
}
prmove(mvg->mvp);
if(optu&4) preval(mvg->val1);
return(mvg->mvp);
}
preval(r) int r; {
pmesg("value: %d\n",r);
pmesg("res[i]: %d %d %d\n",res0,res1,res2);
pmesg("#calls: %d\n",rescct);
}
/* deliver either evaluation or answer '<a' or '>b' */
result(mvpt,a,b) int *mvpt,a,b; {
register int i;
register int *mp1;
int c,ct0,ct,r,res,*mpf0,fp;
rescct++;
mp1 = mvpt;
c = *mp1 & COL;
bord[((*mp1++) & 0377)] = EMPTY;
i = *mp1 & VAL;
bord[((*mp1++) & 0377)] = i;
ct0 = ct = *mp1++;
while(ct--) bord[((*mp1++) & 0377)] = EMPTY;
if(!ct0) rdepth++;
fp = (rdepth/2 == fplevel ? freepath(c) : 0);
a += fp;
b += fp;
if(ct0 || (rdepth<rdmin)) goto go_on;
if((mp-moves > rdif) || (rdepth >= rdmax)) goto eval;
goto go_on;
eval:
res = (*avalue)(c);
goto unmove;
go_on:
mpf0 = mpf;
mpf = mp;
move(COL-c);
res = b+1;
for(mp1=mpf; mp1<mp; ){
r = -result(mp1,-res,-a);
if(r < res){
res = r;
if(res < a) break;
}
mp1 += 2;
mp1 += (*mp1++);
}
mp = mpf;
mpf = mpf0;
unmove:
mp1 = mvpt;
i = *mp1++; /* be careful; perhaps start and
final position are the same! */
bord[((*mp1++) & 0377)] = EMPTY;
bord[i & 0377] = i & VAL;
ct = *mp1++;
while(ct--){
i = *mp1 & VAL;
bord[((*mp1++) & 0377)] = i;
}
if(!ct0) rdepth--;
return(res-fp);
}
/* evaluation of position after recursion */
int info[66] = {
0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 0,
3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 0,
5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 0,
7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 0,
9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 0,
0, 0, 0, 0, 0
};
/* valuations for the columns: index is fldnr%11 */
/* weight center */
int valar1[11] = {
0, 2, 4, 3, 1, UNDEF, 1, 3, 4, 2, 0
};
/* weight distribution */
int valar2[11] = {
-5, -3, -1, 2, 4, UNDEF, -4, -2, 1, 3, 5
};
value(c){
int sum,v,oc;
register int d,*bp,*ip;
oc = COL - c;
sum = 0;
ip = &info[6];
for(bp = &bord[6]; bp < &bord[60]; ){
d = *bp++ & VAL;
v = *ip++;
if(d == EMPTY) continue;
if(d == EDGE) continue;
if(d&DAM){
v = DVAL;
/* increase value if on main diagonal */
if((bp-bord)%5 == 1) v += DMVAL;
} else {
if(d == WHITE) v = 11-v;
v += PVAL;
}
if(d & oc) v = -v;
sum += v;
}
return(sum);
}
/* evaluation of position after recursion */
/* value of tripods : the value of the field they point to */
int info2[66] = {
0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 0,
5, 7, 8, 6, 2,
2, 7, 9, 8, 6, 0,
7, 9, 10, 8, 2,
2, 9, 11, 10, 8, 0,
2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 0,
2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 0,
0, 0, 0, 0, 0
};
int vcentrw,vcentrb,vequidw,vequidb,vtempw,vtempb;
value2(c){
int sum,v,oc;
register int d,*bp,i;
oc = COL - c;
sum = 0;
vcentrw = vcentrb = vequidw = vequidb = vtempw = vtempb = 0;
for(bp = bord; bp < &bord[6]; bp++){
sum += trip(5,BLACK,bp);
sum += trip(6,BLACK,bp);
}
if(c == WHITE) sum = -sum;
for(i=6; i<60; (i++,bp++)){
d = *bp & VAL;
if(d == EMPTY) continue;
if(d == EDGE) {
v = trip(-5,WHITE,bp);
v += trip(-6,WHITE,bp);
v -= trip(5,BLACK,bp);
v -= trip(6,BLACK,bp);
sum += (c == WHITE ? v : -v);
continue;
}
if(d&DAM){
v = DVAL;
/* increase value if on main diagonal */
if((i/5)*5 == i) v += DMVAL;
} else {
v = PVAL;
if(d == WHITE){
vtempw += info[65-i];
v += trip(-5,WHITE,bp);
v += trip(-6,WHITE,bp);
vequidw += valar2[i%11];
vcentrw += valar1[i%11];
} else {
vtempb += info[i];
v += trip(5,BLACK,bp);
v += trip(6,BLACK,bp);
vequidb += valar2[i%11];
vcentrb += valar1[i%11];
}
}
if(d & oc) v = -v;
sum += v;
}
for( ;bp < &bord[66]; bp++){
v = trip(-5,WHITE,bp);
v += trip(-6,WHITE,bp);
sum += (c == WHITE ? v : -v);
}
if(vequidw < 0) vequidw = -vequidw;
if(vequidb < 0) vequidb = -vequidb;
v = vcentrw-vcentrb-vequidw+vequidb+vtempw-vtempb;
sum += (c == WHITE ? v : -v);
return(sum);
}
evalue(c){
int sum,v,oc,i;
register int d,*bp,*ip;
oc = COL-c;
sum = 0;
ip = &info[6];
for(bp = &bord[6]; bp < &bord[60]; ){
d = *bp++ & VAL;
v = *ip++;
if(d == EMPTY) continue;
if(d == EDGE) continue;
/* if opponent has a king then traps are valuable */
if((d==WHITE && bkct) || (d==BLACK && wkct))
v += trap(-5,d&COL,bp)
+ trap(-6,d&COL,bp)
+ trap( 5,d&COL,bp)
+ trap( 6,d&COL,bp);
if(d&DAM) {
v = DVAL;
if((bp-bord)%5 == 1) v += DMVAL;
if(fouragnst1){
i = (bp-bord)%6;
if(i <= 1) v += DMVAL;
switch(bp-bord){
case 6+1:
case 11+1:
case 54+1:
case 59+1:
v += DMVAL/2;
}
}
} else {
if(d == WHITE) v = 11-v;
v += PVAL;
}
if(d & oc) v = -v;
sum += v;
}
return(sum);
}
prsteval(){
int rdmax0,rdmin0;
register int *mp1;
if(optu&1) printf("static eval: %d\n",value2(me));
if(optu&2){
rdmax0 = rdmax;
rdmin0 = rdmin;
rdmax = rdmin = 1;
rdepth = 0;
disp = 0;
avalue = value2;
move(me);
for(mp1=mpf; mp1<mp; ){
printf("%4d ", result(mp1,-GIANT,GIANT));
printf("(%2d %2d %2d / %2d %2d %2d) ",
vtempw-vtempb,vcentrw,vequidw,
vtempb-vtempw,vcentrb,vequidb );
prmove(mp1);
if((mvnr&1)==0) putchar('\n'); /* %% */
mp1 += 2;
mp1 += (*mp1++);
}
printf("\n");
rdmax = rdmax0;
rdmin = rdmin0;
}
}
/* test for X XY where Y=X or Y=Edge */
trap(dir,col,nbp) int dir,col,*nbp; {
register int *bp,w,v;
bp = nbp+dir;
if(*bp != EMPTY) return(0);
bp += dir;
if(((w = *bp)&COL) != col) return(0);
bp += dir;
if(!(*bp & col)) return(0);
/* value is number of empty fields covered by trap */
v = 0;
bp = nbp-dir;
while(*bp == EMPTY){
v += TPVAL;
bp -= dir;
}
/* extra bonus if base of trap is a king */
if(w & DAM) v += (v/2);
return(v);
}
trip(dir,col,nbp) int dir,col,*nbp; {
register int *bp;
int tv1,tv2;
tv2 = 0;
bp = nbp+dir;
if(*bp != col) return(0);
bp += dir;
if(*bp != col) return(0);
tv1 = (col == WHITE ? info2[65-(bp+dir-bord)] : info2[bp+dir-bord]);
if(bp[dir] == col) tv1 >>= 1;
if(dir < 0) dir = -dir;
dir = 11-dir; /* interchange 5 and 6 */
if(bp[dir] == col && ((bp[dir+dir] & col) == 0)) tv2++; else
if(bp[-dir]== col && ((bp[-dir-dir]& col) == 0)) tv2++;
return(tv2 ? 2 : tv1);
}
/* check for free path (for oc) to a king */
int freect,frlngt,flth; /* 'real' free path */
int freect2,frlngt2,fbcct; /* free paths discarding backward captures */
int fpval[11] = {
0, /* 0 cannot occur */
PVAL, /* 1 is already seen as a king in recursion %% */
PVAL, /* 2 */
PVAL-10, /* 3 */
PVAL-20, /* 4 */
PVAL/2, /* 5 */
30,30, /* 6,7 */
15,15, /* 8,9 */
0 /* 10, i.e. no free paths */
};
int fpval2[11] = {
0, 0, /* 0,1 cannot occur */
PVAL/2, /* 2 */
PVAL/3, /* 3 */
10,10, /* 4,5 */
5,5, /* 6,7 */
2,2, /* 8,9 */
0 /* 10 */
};
freepath(c) int c; {
register int *bp,*nbp,i;
int nbord[66],oc;
oc = COL-c;
/* copy */
bp = bord;
nbp = nbord;
while(bp < &bord[66]) *nbp++ = *bp++;
/* swell */
for(nbp = &nbord[6]; nbp < &nbord[60]; nbp++){
if((*nbp & COL) == c){
if(*nbp & DAM) {
dmark(nbp, -6);
dmark(nbp, -5);
dmark(nbp, 5);
dmark(nbp, 6);
} else {
if(c == WHITE){
nbp[-6] |= FLAGS;
nbp[-5] |= FLAGS;
nbp[5] |= FLAG;
nbp[6] |= FLAG;
} else {
nbp[-6] |= FLAG;
nbp[-5] |= FLAG;
nbp[5] |= FLAGS;
nbp[6] |= FLAGS;
}
}
*nbp = EDGE;
}
}
/* but note: points on the border are always safe */
nbp = nbord;
for(i = 6; i<10; i++) nbp[i] &= VAL;
for( ; i<65; i += 10){
nbp[i++] &= VAL;
nbp[i] &= VAL;
}
for(i = 56; i<60; i++) nbp[i] &= VAL;
/* determine strong component of last line */
freect = flth = freect2 = fbcct = 0;
frlngt = frlngt2 = 10; /* shortest freepath: +inf */
if(c == WHITE){
for(nbp = &nbord[55]; nbp < &nbord[60]; nbp++)
reach(oc,nbp,-6);
} else for(nbp = &nbord[6]; nbp < &nbord[11]; nbp++)
reach(oc,nbp,5);
if(debug){ /* %% */
pmesg("fct: %d, fct2: %d, fl: %d, fl2: %d,\
flth: %d=0, fbcct: %d=0\n",
freect,freect2,frlngt,frlngt2,flth,fbcct);
}
if(freect) return(fpval[frlngt]);
return(fpval2[frlngt2]);
}
dmark(nbp,d) int *nbp,d; {
register int *bp;
bp = nbp + d;
while((*bp & COL) == EMPTY){
*bp = FLAGS;
bp += d;
}
}
reach(oc,nbp,d) int oc,*nbp,d; {
register int *bp,v;
bp = nbp;
v = *bp & VAL;
if(v == EDGE) return;
if(v == oc) {
if(fbcct == 0){
freect++;
if(frlngt > flth) frlngt=flth;
} else {
freect2++;
if(frlngt2 > flth) frlngt2=flth;
}
}
if(v != EMPTY) return; /* %% */
if((*bp & FLAG) == 0){
flth++;
reach(oc,bp+d,d);
reach(oc,bp+d+1,d);
flth--;
if(fbcct == 0) *bp = EDGE;
else *bp |= FLAG2; /* dont look for semifree paths */
} else if((*bp & FLAG2) == 0){
fbcct++;
flth++;
reach(oc,bp+d,d);
reach(oc,bp+d+1,d);
flth--;
fbcct--;
*bp = EDGE; /* dont return to this field */
} else *bp = EDGE;
}
/* construct position after move k */
backup(k) int k; {
register int i,*gp0;
int mvno,c,ct;
/* the validity of k was checked by the caller */
if(rdbord[0])
for(i=6; i<60; i++){
if(bord[i] != EDGE) bord[i] = rdbord[i];
}
else {
for(i=1; i<=20; i++) bord[conv[i]] = BLACK;
for(i=21;i<=30; i++) bord[conv[i]] = EMPTY;
for(i=31;i<=50; i++) bord[conv[i]] = WHITE;
}
gp0 = game;
mvno = mvnr;
mvnr = 1;
while(k--){
mvnr++;
c = *gp0 & COL;
if(mvnr == crownmv) crown(c); /* yields output %% */
bord[(*gp0++) & 0377] = EMPTY;
i = *gp0 & VAL;
bord[(*gp0++) & 0377] = i;
ct = *gp0++;
while(ct--) bord[(*gp0++) & 0377] = EMPTY;
}
mvnr++;
if((mvno+mvnr) & 1) me = COL-me;
mpf = 0; /* the position has changed */
gp = gp0;
if(lasthap > mvnr) lasthap = mvnr;
if(crownmv > mvnr) crownmv = 0;
}
/*
* Implemented rules:
*
* a) If the same position occurs thrice (with the same
* player to move) it is a draw.
* b) If a player has 3 pieces among which at least one
* king and his opponent has one king only, his opponent
* may crown all these pieces (which action does not
* count for a move). Immediately rule c) becomes applicable.
* c) If the position is 3 kings against 1 king then after
* (single king on main diagonal ? 3 : 10)
* moves the game ends in a draw.
*
* In addition to these we use for PDP against PDP play the rule:
*
* z) If during DRAWWT moves no piece has been captured and only
* kings have moved it is a draw.
*
*/