From bbae73a06cdb4f85eb1d4dec684faeea0f9ac369 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Mon, 11 Feb 2013 23:00:22 +0100 Subject: [PATCH] Discount score when mating potential in jeopardy A new routine is added to the search, to determine the right-shift of the score when the leading side does nor have mating potential, its last Pawn is in jeopardy and no mating potential will be left, or when it has no Pawns to begin with (even with mating potential). The heuristic for mating potential can be fine-tuned by hiding some flags in the pair bonus field, for 'mating minor', 'deficient pair' or 'tough defender'. --- fairymax.c | 59 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 42 insertions(+), 17 deletions(-) diff --git a/fairymax.c b/fairymax.c index 54bcf60..bdb76e4 100644 --- a/fairymax.c +++ b/fairymax.c @@ -124,7 +124,7 @@ struct _ {int K,V;char X,Y,D,F;} *A; /* hash table, 16M+8 entries*/ int M=136,S=128,I=8e3,Q,O,K,N,j,R,J,Z,LL,GT, /* M=0x88 */ BW,BH,sh, -w[16]={0,2,2,-1,7,8,12,23,7,5}, /* relative piece values */ +w[32]={0,2,2,-1,7,8,12,23,7,5}, /* relative piece values */ o[256], oo[32], /* initial piece setup */ of[256], @@ -145,14 +145,14 @@ void pboard() } -D(k,q,l,e,E,z,n) /* recursive minimax search, k=moving side, n=depth*/ -int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ +D(k,q,l,e,ev,E,z,n) /* recursive minimax search, k=moving side, n=depth*/ +int k,q,l,e,ev,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ { /* e=score, z=prev.dest; J,Z=hashkeys; return score*/ - int j,r,m,v,d,h,i,F,G,P,V,f=J,g=Z,C,s,flag,FF,*ps=sp,kk=S; + int j,r,m,v,d,h,i,F,G,P,V,f=J,g=Z,C,s,flag,FF,*ps=sp,kk=S,re; signed char t,p,u,x,y,X,Y,H,B,gt; struct _*a=A+(J+(k+S)*E&U); /* lookup pos. in hash table*/ *sp++=0; - q-=qD;m=a->V;X=a->F;Y=a->Y; /* resume at stored depth */ if(a->K-Z|z&S | /* miss: other pos. or empty*/ !(m<=q|X&8&&m>=l|X&S)) /* or window incompatible */ @@ -163,8 +163,8 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ (K=X,L=Y&~S,Score=m,d=3))) /* time's up: go do best */ {x=B=X; /* start scan at prev. best */ h=Y&S; /* request try noncastl. 1st*/ - P=d>2&&l+I?D(16-k,-l,1-l,-e,2*S,2*S,d-3):I; /* search null move */ - m=-P beta unconsidered:static eval */ + P=d>2&&l+I?D(16-k,-l,1-l,-e,-ev,2*S,2*S,d-3):I; /* search null move */ + m=-P beta unconsidered:static eval */ SHAMAX( if(pl[k]<=1&pl[16-k]>1)m=I-1; ) /* bare king loses */ N++; /* node count (for timing) */ do{u=b[x]; /* scan board looking for */ @@ -195,7 +195,7 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ if(i<0&&(pl[t&31]<2|| /* K capture, (of last K), */ t>>3&kk!=H&kk!=S||(kk=H,i=-i,0)))m=I,d=98;/* or duple check: cutoff*/ if(m>=l&d>1)goto C; /* abort on fail high */ - v=d-1?e:i-p; /*** MVV/LVA scoring if d=1**/ + v=d-1?ev:i-p; /*** MVV/LVA scoring if d=1**/ if(d-!t>1) /*** all captures if d=2 ***/ {v=gt=0;G: /* retry move with gating */ v+=centr[p]?b[x+257]-b[y+257]:0; /* center positional pts. */ @@ -216,12 +216,13 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ J+=J(0);Z+=J(4)+G-S; pl[k]-=!!t; /* count pieces per side */ v+=e+i;V=m>q?m:q; /*** new eval & alpha ****/ + re=v>>Fac(v>>15&16^k); /* Reduce eval if drawish for leading side */ if(z&S)V=m-margin>q?m-margin:q; /* multiPV */ C=d-1-(d>5&p>2&!t&!h); /* nw depth, reduce non-cpt.*/ C=R2|v>V?-D(16-k,-l,-V,-v,/*** futility, recursive eval. of reply */ - F,y&255,C):v; + s=C>2|re>V?-D(16-k,-l,-V,/*** futility, recursive eval. of reply */ + -v,-re,F,y&255,C):re; W(s>q&++CV&v1)h-=pl[++i],e-=pl[i]*w[i]; /* total value his remaining*/ + if(!h)e+=3*w[i]; /* dual King, correct w[]<0 */ + j&=pb[i]==-1; /* tough defenders left */ + for(i=k+3,h=m;h>1;h-=pl[i++])e+=pl[i]*w[i],/* lead in piece material */ + f|=pl[i]&pb[i]/*,printf("%d,%d,%d=%d,%d ",i,pl[i],pb[i],e,f)*/; /* detect mating minors */ + if(!f&&e<350 /* non-mating minor ahead */ + ||m-1&(pb[--i]>3|j) /* single color-bound or vs tough */ + ||pl[i]==2&pb[i]<-1)r=3-n; /* non-mating pair */ + }}} + return r; +} /* Generic main() for Winboard-compatible engine */ /* (Inspired by TSCP) */ @@ -342,7 +367,7 @@ int PrintResult(int s) differs: ; } K=I; - cnt = D(s,-I,I,Q,O,LL|4*S,3); + cnt = D(s,-I,I,Q,Q,O,LL|4*S,3); #ifdef SHATRANJ if(pl[s]==1 && pl[16-s]==1) { printf("1/2-1/2 {Insufficient mating material}\n"); @@ -509,7 +534,7 @@ void LoadGame(char *name) while(fscanf(f, "%d,%x", o+j, of+j)==2 || fscanf(f,"%c:%d",&c, w+i+1)==2) { if(c) - { od[++i]=j; centr[i] = c>='a'; + { od[++i]=j; centr[i] = c>='a'; w[i+16] = w[i]; blacktype[c&31]=i; piecename[i]=c&31; if(piecetype[c&31]==0) piecetype[c&31]=i; // only first pb[i] = pb[i+16] = w[i]>>3 & ~3; // pair bonus, for now 1/8 of piece value, leave low bits for flag @@ -579,7 +604,7 @@ int main(int argc, char **argv) if(tlim>TimeLeft/15) tlim = TimeLeft/15; PromPiece = 0; /* Always promote to Queen ourselves */ N=0;K=I; - if (D(Side,-I,I,Q,O,LL|S,3)==I) { + if (D(Side,-I,I,Q,Q,O,LL|S,3)==I) { Side ^= BLACK^WHITE; m = GetTickCount() - Ticks; printf("# times @ %u: real=%d cpu=%1.0f\n", m + Ticks, m, @@ -763,7 +788,7 @@ int main(int argc, char **argv) } if (!strcmp(command, "hint")) { Ticks = GetTickCount(); tlim = 1000; - D(Side,-I,I,Q,O,LL|4*S,6); + D(Side,-I,I,Q,Q,O,LL|4*S,6); if (K==0 && L==0) continue; printf("Hint: "); @@ -793,7 +818,7 @@ int main(int argc, char **argv) for(i=0; i<=U; i++) A[i].D = A[i].K = 0; // clear hash table for(nr=0; nrL ? i-1 : i+2; } if((b[K]&15) < 3) GT = 0; // Pawn => true promotion rather than gating - if(D(Side,-I,I,Q,O,LL|S,3)!=I) { + if(D(Side,-I,I,Q,Q,O,LL|S,3)!=I) { /* did have move syntax, but illegal move */ printf("Illegal move:%s\n", line); } else { /* legal move, perform it */ -- 1.7.0.4