X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=fairymax.c;h=46b3890cdafdbb0c39b4149e15d7cc401e942ec8;hb=pairomax;hp=20b63ddfcc0ec3f8242f52bbe642268a18a98fda;hpb=a6e756fc912dd7c895816bd5b117b080bc84b582;p=fairymax.git diff --git a/fairymax.c b/fairymax.c index 20b63dd..46b3890 100644 --- a/fairymax.c +++ b/fairymax.c @@ -18,7 +18,7 @@ /*****************************************************************/ #define MULTIPATH -#define VERSION "4.8R" +#define VERSION "4.8S" #include #include @@ -73,7 +73,7 @@ int StartKey; #else # define FAC 128 # define EG 10 -# define NAME "Fairy-Max" +# define NAME "Pair-o-Max" # define SHAMAX(x) # define FMAX(x) x #endif @@ -124,13 +124,13 @@ 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], od[16]; /* 1st dir. in o[] per piece*/ -signed char L,pl[32], +signed char L,pl[32],pb[32], b[513], /* board: 16x8+dummy, + PST */ T[4104], /* hash translation table */ centr[32], @@ -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=n>2&d>1&&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,13 +195,13 @@ 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. */ if(!(G&S))b[FF]=b[G],v+=50; /* castling: put R & score */ b[G]=b[H]=0;b[x]=gt;b[y]=u|32; /* do move, set non-virgin */ - pl[t&31]-=!!t; /* updat victim piece count */ + i+=-((pl[t&31]-=!!t)&1)&pb[t&31];/* update piece count, pair bonus */ v-=w[p]>0|R>10&31)-16; J+=J(0);Z+=J(4)+G-S; - SHAMAX( pl[k]-=!!t; ) /* count pieces per side */ + 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=R0?C:d; /* extend 1 ply if in-check */ do - s=C>2|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&vD=99;a->V=0; /* lock game in hash as draw*/ R-=i/FAC; /*** total captd material ***/ Fifty = t|p<3?0:Fifty+1; @@ -240,7 +242,7 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ return l;} /* & not in check, signal */ v=m; /* (prevent fail-lows on */ } /* K-capt. replies) */ - SHAMAX( pl[k]+=!!t; ) pl[t&31]+=!!t; + pl[k]+=!!t;pl[t&31]+=!!t; b[G]=b[FF];b[FF]=b[y]=0;b[x]=u;b[H]=t; /* undo move,G can be dummy */ } /* if non-castling */ if(z&S&&K==I&d>2&v>V&v0){ /* can sac, <= 1 piece left */ + i=18-k;W(!pl[++i]); /* get lowest piece */ + e=abs(w[i--])*n; /* sac for Pawn (if any) */ + W(h>1)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 +368,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"); @@ -404,6 +430,7 @@ void InitGame() for(i=0; i>1)*pb[i] -(pl[i+16]>>1)*pb[i]; if(w[oo[i]] < 0) k = w[oo[i]]; } R -= 2*(-k/FAC); @@ -464,7 +491,7 @@ void PrintOptions() void LoadGame(char *name) { - int i, j, ptc, count=0; char c, buf[80], pieceToChar[80]; + int i, j, ptc, count=0; char c, buf[80], pieceToChar[80], parent[80]; static int currentVariant; FILE *f; @@ -482,7 +509,7 @@ void LoadGame(char *name) if(!strcmp(name, "makruk") && Cambodian) name = "cambodian"; else if(!strcmp(name, "fairy")) name = selectedFairy; gating = !strcmp(name, "seirawan"); - while((ptc=fscanf(f, "Game: %s # %s", buf, pieceToChar))==0 || strcmp(name, buf) ) { + while((ptc=fscanf(f, "Game: %s # %s %s", buf, pieceToChar, parent))==0 || strcmp(name, buf) ) { while((c = fgetc(f)) != EOF && c != '\n'); count++; if(c == EOF) { @@ -508,10 +535,14 @@ 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 succession |= w[i] < -4; // expendable royalty; assume we can promote to it + } else { + if((o[j]^o[j]+8>>4)&1 || of[j]>>4) pb[i] = pb[i+16] = 0; // not color bound (or too complex to see it), so no pair bonus + if(!o[j]) pb[i] = pb[i+16] = of[j--]; // hand-set pair bonus kludges: 3 for mating minor, negative for non-mating pair. } j++; o[j]=0; /* printf("# c='%c' i=%d od[i]=%d j=%d (%3d,%8x)\n",c?c:' ',i,od[i],j,o[j-1],of[j-1]); /**/ @@ -521,8 +552,9 @@ void LoadGame(char *name) fclose(f); sh = w[7] < 250 ? 3 : 0; makruk = w[7]==181 ? 64 : 0; // w[7] is used as kludge to enable makruk promotions - if(name == selectedFairy) { - printf(ptc == 1 ? "setup " : "setup (%s) ", pieceToChar); // setup board in GUI + if(ptc > 1) { // setup board in GUI, by sending it pieceToCharTable and FEN + if(ptc == 2) printf("setup (%s) ", pieceToChar); + else printf("setup (%s) %dx%d+0_%s", pieceToChar, BW, BH, parent); for(i=0; iTimeLeft/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, @@ -742,7 +774,7 @@ int main(int argc, char **argv) if(sscanf(line+7, "Ini File=%s", filename) == 1) { inifile = filename; continue; } - if(sscanf(line+7, "Clear Hash%c", &c) == 1) for(i=0; i<=U; i++) A->K = 0; + if(sscanf(line+7, "Clear Hash%c", &c) == 1) for(i=0; i<=U; i++) A[i].K = 0; if(sscanf(line+7, "MultiVariation Margin=%d", &margin) == 1) continue; if(sscanf(line+7, "Variant fairy selects=%s", selectedFairy+6) == 1) continue; if(sscanf(line+7, "Cambodian Makruk rules=%d", &Cambodian) == 1) continue; @@ -758,7 +790,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: "); @@ -788,7 +820,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; nr= 'a' && line[1] <= 'a'+BW-1 && line[2] >= '1' && line[2] <= '0'+BH) { - m = line[1]-16*line[2]+799; + m = line[1]-16*line[2]+799; r = m & 0x70; switch(p) { case 1: case 2: if(color==WHITE) - b[m]=(m&0x70)==0x60?1:33, - Q+=w[1]; - else b[m]=(m&0x70)==0x10?18:50, - Q+=w[2]; + b[m]=r==0x10?161:r==0x20?97:r==0x60?1:33, + Q+=w[1]+(r==0x10?S:r==0x20?64:0); + else b[m]=r==0x60?178:r==0x50?114:r==0x10?18:50, + Q+=w[2]+(r==0x60?S:r==0x50?64:0); break; default: b[m]=p+color+32; // assume non-virgin @@ -857,7 +889,7 @@ int main(int argc, char **argv) case 0: // undefined piece, ignore break; } - pl[BLACK+WHITE-color]++;pl[p+color]++; + pl[BLACK+WHITE-color]++; if(pl[p+color]++&1) Q+=pb[p]; if(w[p+color] == -1)pl[p+color]=1; // fake we have one if value = -1, to thwart extinction condition continue; } @@ -886,9 +918,8 @@ int main(int argc, char **argv) else { int i=-1; if(b[L] && (b[L]&16) == Side && w[b[L]&15] < 0) // capture own King: castling { i=K; K = L; L = i>L ? i-1 : i+2; } - if(w[GT&15] < -1) pl[GT&31]++, J+=89729; // promotion to royal piece 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 */