From: H.G. Muller Date: Mon, 11 Feb 2013 22:00:22 +0000 (+0100) Subject: Discount score when mating potential in jeopardy X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=bbae73a06cdb4f85eb1d4dec684faeea0f9ac369;p=fairymax.git 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'. --- 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 */