From d49765690831138d5d4debc822c71398bd72df36 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Wed, 1 Dec 2010 17:12:27 +0100 Subject: [PATCH] Better implementation of Seirawan Chess The previous implementation gated 'blindly', without gating being considered in the search. Now the gating is put in the search, by assigning the variable gt (initialized to 0) to the from square in stead of a straight 0 (= empty square), when making the move. An extra loop (alas, goto-based) then steps gt through the available pieces (removing and putting them back into the holdings) when the moved piece is a virgin non-Pawn and the variant allows gating. In the root the value of gt for the best move is remembered in the global variable GT, while searching (i.e. K==I). This can also be set from the promoChar of an input move. The pass to perform the move (with K != I) then compares gt to GT when testing for legality. fix --- data/fmax.ini | 9 +++++---- fairymax.c | 55 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/data/fmax.ini b/data/fmax.ini index 1c1a6db..5e006c2 100644 --- a/data/fmax.ini +++ b/data/fmax.ini @@ -415,17 +415,18 @@ d:625 1,7 16,7 -1,7 -16,7 15,3 17,3 -15,3 -17,3 // Seirawan Chess (with Archbishop and Chancellor gated in during game) Game: seirawan 8x8 -5 3 4 7 9 4 3 5 -5 3 4 7 9 4 3 5 +5 3 4 7 6 4 3 5 +5 3 4 7 6 4 3 5 p:74 -16,24 -16,6 -15,5 -17,5 p:74 16,24 16,6 15,5 17,5 n:259 14,7 31,7 33,7 18,7 -14,7 -31,7 -33,7 -18,7 b:296 15,3 17,3 -15,3 -17,3 R:444 1,3 16,3 -1,3 -16,3 -h:780 15,3 17,3 -15,3 -17,3 14,7 31,7 33,7 18,7 -14,7 -31,7 -33,7 -18,7 +k:-1 1,34 -1,34 1,7 16,7 15,7 17,7 -1,7 -16,7 -15,7 -17,7 Q:851 1,3 16,3 15,3 17,3 -1,3 -16,3 -15,3 -17,3 -E:814 1,3 16,3 -1,3 -16,3 14,7 31,7 33,7 18,7 -14,7 -31,7 -33,7 -18,7 k:-1 1,34 -1,34 1,7 16,7 15,7 17,7 -1,7 -16,7 -15,7 -17,7 +h:780 15,3 17,3 -15,3 -17,3 14,7 31,7 33,7 18,7 -14,7 -31,7 -33,7 -18,7 +E:814 1,3 16,3 -1,3 -16,3 14,7 31,7 33,7 18,7 -14,7 -31,7 -33,7 -18,7 // Spartan Chess, where black has a different army from white's orthodox FIDE, with two kings Game: fairy/Spartan # PNBRQ..............K....q.lwg.....c...hk diff --git a/fairymax.c b/fairymax.c index 0f4dd5f..c135fb6 100644 --- a/fairymax.c +++ b/fairymax.c @@ -111,7 +111,7 @@ int GamePtr, HistPtr; int U=(1<<23)-1; 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, /* M=0x88 */ +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 */ o[256], @@ -138,7 +138,7 @@ 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.*/ { /* 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; - signed char t,p,u,x,y,X,Y,H,B; + signed char t,p,u,x,y,X,Y,H,B,gt; struct _*a=A+(J+(k+S)*E&U-1); /* lookup pos. in hash table*/ *sp++=0; q-=q=l&d>1)goto C; /* abort on fail high */ v=d-1?e:i-p; /*** MVV/LVA scoring if d=1**/ if(d-!t>1) /*** all captures if d=2 ***/ - {v=centr[p]?b[x+257]-b[y+257]:0; /* center positional pts. */ + {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]=b[x]=0;b[y]=u|32; /* do move, set non-virgin */ + 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 */ v-=w[p]>0|RD=99;a->V=0; /* lock game in hash as draw*/ R-=i/FAC; /*** total captd material ***/ Fifty = t|p<3?0:Fifty+1; sp=ps; - if(!(u&32)&PromPiece&(K&112)==(k?0:112)) - prom=b[K]=39+k-PromPiece,J+=333,pl[k+14-PromPiece]--; /* gating */ return l;} /* & not in check, signal */ v=m; /* (prevent fail-lows on */ } /* K-capt. replies) */ - J=f;Z=g; SHAMAX( 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&&Post&K==I&d>2&v>V&v>8;Y=*p++; - printf(" %c%c%c%c",'a'+(X&15),'8'-(X>>4),'a'+(Y&15),'8'-(Y>>4&7));} - printf("\n");fflush(stdout); + if(z&S&&K==I&d>2&v>V&v>8;Y=*p++; + printf(" %c%c%c%c",'a'+(X&15),'8'-(X>>4),'a'+(Y&15),'8'-(Y>>4&7));} + printf("\n");fflush(stdout); + }GT=gt; /* In root, remember gated */ } if(v>m) /* new best, update max,best*/ m=v,X=x,Y=y|S&F; /* mark non-double with S */ + if(gating&&!(u&32)&&p>2&&d-!t>1){ /* virgin non-Pawn: gate */ + pl[(gt|=k+40)-27]++; /* prev. gated back in hand */ + if(m>=l)goto C; /* loop skips cutoff :-( */ + W(++gt>12; /* calc. alternated vector */ @@ -389,7 +396,7 @@ InitGame() R -= 2*(-k/FAC); UnderProm = -1; pl[WHITE] = pl[BLACK] = 2*BW; pm = !pl[BLACK+7] && pl[BLACK+9] && pl[WHITE+7] ? 2 : 0; // Unlike white, black has no 'Q', so promote to 9, which he does have. - if(gating) pl[13] = pl[15] = pl[29] = pl[31] = 1, R += 2*(w[6]/FAC + w[8]/FAC); + if(gating) pl[14] = pl[15] = pl[30] = pl[31] = 1, R += 2*(w[9]/FAC + w[10]/FAC); } void CopyBoard(int s) @@ -455,10 +462,10 @@ int LoadGame(char *name) if(fscanf(f, "version 4.8(%c)", &c)!=1 || c != 'w') { printf("telluser incompatible fmax.ini file\n"); exit(0); } - gating = 0; + gating = 0; if(name != NULL) { /* search for game name in definition file */ - if(!strcmp(name, "fairy")) name = selectedFairy; + if(!strcmp(name, "fairy")) name = selectedFairy; gating = !strcmp(name, "seirawan"); while((ptc=fscanf(f, "Game: %s # %s", buf, pieceToChar))==0 || strcmp(name, buf) ) { while((c = fgetc(f)) != EOF && c != '\n'); @@ -549,12 +556,9 @@ int main(int argc, char **argv) tlim = (0.6-0.06*(BW-8))*(TimeLeft+(m-1)*TimeInc)/(m+7); if(tlim>TimeLeft/15) tlim = TimeLeft/15; PromPiece = 0; /* Always promote to Queen ourselves */ - if(pl[Side+13])PromPiece=1;else if(pl[Side+15])PromPiece=-1; /* S-Chess gating */ N=0;K=I; if (D(Side,-I,I,Q,O,LL|S,3)==I) { Side ^= BLACK^WHITE; - if(b[K]&&Score+D(Side,-I,I,Q,2*S,2*S,2)>S) - prom=b[K]=0,J-=333,pl[30-Side-PromPiece]++; /* undo bad gating */ if(UnderProm>=0 && UnderProm != L) { printf("tellics I hate under-promotions!\n"); printf("resign { underpromotion } \n"); @@ -853,8 +857,8 @@ int main(int argc, char **argv) m = line[0]<'a' | line[0]>='a'+BW | line[1]<'1' | line[1]>='1'+BH | line[2]<'a' | line[2]>='a'+BW | line[3]<'1' | line[3]>='1'+BH; if(line[4] == '\n') line[4] = 0; - PromPiece = (Side == WHITE ? piecetype : blacktype)[line[4]&31]; - if(PromPiece) PromPiece = (Side == WHITE ? 7 : 7+pm) - PromPiece; + GT = (Side == WHITE ? piecetype : blacktype)[line[4]&31]; + if(GT) PromPiece = (Side == WHITE ? 7 : 7+pm) - GT, GT |= 32 + Side; {char *c=line; K=c[0]-16*c[1]+799;L=c[2]-16*c[3]+799; } if (m) /* doesn't have move syntax */ @@ -862,10 +866,11 @@ 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(b[K]&32) GT = 0; // non-virgin mover => true promotion rather than gating if(D(Side,-I,I,Q,O,LL|S,3)!=I) { /* did have move syntax, but illegal move */ printf("Illegal move:%s\n", line); - } else { /* legal move, perform it */ + } else { /* legal move, perform it */ if(i >= 0) b[i]=b[K],b[K]=0; // reverse Seirawan gating GameHistory[GamePtr++] = PACK_MOVE; Side ^= BLACK^WHITE; -- 1.7.0.4