X-Git-Url: http://winboard.nl/cgi-bin?p=fairymax.git;a=blobdiff_plain;f=fairymax.c;h=5df22c20e28ca706ede553c0db616316619dee94;hp=6305a449b2c23b7dd3cc81578dbe5c87f6ea632e;hb=HEAD;hpb=18e3a22339d477d3d27550a9fe49aaaed0c14fff diff --git a/fairymax.c b/fairymax.c index 6305a44..5df22c2 100644 --- a/fairymax.c +++ b/fairymax.c @@ -1,13 +1,16 @@ /***************************************************************************/ -/* fairy-Max, */ +/* Fairy-Max, */ /* Version of the sub-2KB (source) micro-Max Chess program, fused to a */ /* generic WinBoard interface, loading its move-generator tables from file */ /***************************************************************************/ /*****************************************************************/ /* LICENCE NOTIFICATION */ - /* Fairy-Max 4.8 is free software, and you have my permission do */ - /* with it whatever you want, whether it is commercial or not. */ + /* Fairy-Max 4.8 is free software, released in the public domain */ + /* so that you have my permission do with it whatever you want, */ + /* whether it is commercial or not, at your own risk. Those that */ + /* are not comfortable with this, can also use or redistribute */ + /* it under the GNU Public License or the MIT License. */ /* Note, however, that Fairy-Max can easily be configured through*/ /* its fmax.ini file to play Chess variants that are legally pro-*/ /* tected by patents, and that to do so would also require per- */ @@ -18,7 +21,7 @@ /*****************************************************************/ #define MULTIPATH -#define VERSION "4.8O" +#define VERSION "4.8V" #include #include @@ -32,13 +35,24 @@ #ifdef WIN32 # include +# define CPUtime 1000.*clock #else # include +# include +# include int GetTickCount() // with thanks to Tord { struct timeval t; gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } + double CPUtime() + { // get CPU time used by process, converted to 'MILLICLOCKS' + struct tms cpuTimes; + static int cps = 0; + if(!cps) cps = sysconf(_SC_CLK_TCK); + times(&cpuTimes); + return ((double)(cpuTimes.tms_utime + cpuTimes.tms_stime) * CLOCKS_PER_SEC * 1000)/cps; + } #endif int StartKey; @@ -68,10 +82,10 @@ int StartKey; #endif /* make unique integer from engine move representation */ -#define PACK_MOVE 256*K + L; +#define PACK_MOVE 256*K + L + (PromPiece << 16) + (GT<<24); /* convert intger argument back to engine move representation */ -#define UNPACK_MOVE(A) K = (A)>>8 & 255; L = (A) & 255; +#define UNPACK_MOVE(A) K = (A)>>8 & 255; L = (A) & 255; PromPiece = (A)>>16 & 255; GT = (A)>>24 & 255; /* Global variables visible to engine. Normally they */ /* would be replaced by the names under which these */ @@ -87,20 +101,23 @@ int MovesLeft; int MaxDepth; int Post; int Fifty; -int UnderProm; int GameNr; int Resign; +char Cambodian[80] = "makruk"; int Threshold = 800; +int drawMoves = 50; int Score; int makruk; -int prom; +int prom, pm, gating, succession, hill; char piecename[32], piecetype[32], blacktype[32]; +char selectedFairy[80]; char *inifile = INI_FILE; +char info[999]; int Ticks, tlim, Setup, SetupQ; int GameHistory[1024]; -char HistoryBoards[1024][STATE], setupPosition[131]; +char HistoryBoards[1024][STATE], setupPosition[162]; int GamePtr, HistPtr; #define W while @@ -110,7 +127,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], @@ -118,7 +135,7 @@ oo[32], /* initial piece setup */ of[256], od[16]; /* 1st dir. in o[] per piece*/ -signed char L,pl[17], +signed char L,pl[32], b[513], /* board: 16x8+dummy, + PST */ T[4104], /* hash translation table */ centr[32], @@ -127,7 +144,7 @@ n[]=".*XKNBRQEWFMACHG?x+knbrqewfmachg"; /* piece symbols on printout*/ int pv[10000],*sp=pv; // triangular array int margin; -pboard() +void pboard() {int i; i=-1;W(++i<128)printf(" %c",(i&15)==BW&&(i+=15-BW)?10:n[b[i]&31]); } @@ -136,9 +153,9 @@ 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.*/ { /* 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; - signed char t,p,u,x,y,X,Y,H,B; - struct _*a=A+(J+(k+S)*E&U-1); /* lookup pos. in hash table*/ + 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,gt,rg,rk; + 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 */ @@ -158,11 +175,12 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ do{u=b[x]; /* scan board looking for */ if(u&&(u&16)==k) /* own piece (inefficient!)*/ {r=p=u&15; /* p = piece type (set r>0) */ + if(hill&&w[p]<0&b[385+x])m=I,d=98; /* King on the hill: we won */ j=od[p]; /* first step vector f.piece*/ W(r=o[++j]) /* loop over directions o[] */ {A: /* resume normal after best */ flag=h?3:of[j]; /* move modes (for fairies) */ - y=x;F=FF=G=S; /* (x,y)=move, (F,G)=castl.R*/ + y=x;F=FF=G=S;rg=flag>>10&3; /* (x,y)=move, (F,G)=castl.R*/ do{ /* y traverses ray, or: */ H=y=h?Y^h:y+r; /* sneak in prev. best move */ if(flag&1<<8)H=y=(y&15)>13?y+BW:(y&15)>=BW?y-BW:y; /* cylinder board */ @@ -175,25 +193,28 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ } #endif m=E<16|(E^112)<16&&flag&1&y-E<2&E-y<2?I:m; /* bad castling */ - if(p<3&y==E)H=z&127; /* shift capt.sqr. H if e.p.*/ + if(p<3&y==E&flag)H=z&127; /* shift capt.sqr. H if e.p.*/ t=b[H]; if(flag&1+!t) /* mode (capt/nonc) allowed?*/ {if(t&&(t&16)==k)break; /* capture own */ i=w[t&15]+((t&192)>>sh); /* value of capt. piece t */ - if(i<0)m=I,d=98; /* K capture */ + 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**/ if(d-!t>1) /*** all captures if d=2 ***/ - {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 */ + {v=gt=0;G: /* retry move with gating */ + v+=centr[p]*(b[x+257]-b[y+257]); /* center positional pts. */ + if(G-S)b[FF]=(rk=b[G])|32,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 */ v-=w[p]>0|R>2); /* end-game Pawn-push bonus */ - b[y]+=V=y+r+1&S?647-p:2*(u&y+16&32); /* upgrade P or convert to Q*/ + b[y]+=V=y+r+1&S?647-p|pm:2*(u&y+16&32);/*upgrade P or convert to Q*/ if(V&makruk)b[y]=u|7,V=480; /* Makruk promotion on 6th */ V>>=sh; /* for Shatranj promo to F */ i+=V; /* promotion / passer bonus */ @@ -203,7 +224,7 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ v+=e+i;V=m>q?m:q; /*** new eval & alpha ****/ 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; @@ -214,42 +235,52 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ *ps=256*x+y; } if(z&S&&K-I) /* move pending: check legal*/ - {if(v+I&&x==K&y==L) /* if move found */ - {Q=-e-i;O=F;LL=L;prom=0; - if(b[y]-u&15)prom=b[y]-=PromPiece, /* under-promotion, correct */ - J+=PromPiece; /* piece & invalidate hash */ + {if(v+I&&x==K&y==L>==GT) /* if move found */ + {Q=-e-i;O=F;LL=L;prom=gt&15; + if(b[y]-u&15)prom=b[y]-=PromPiece, /* (under-)promotion: */ + Q-=abs(w[prom&=15])-w[p]-(6*S>>sh), /* correct piece & score & */ + Z+=PromPiece; /* invalidate hash */ a->D=99;a->V=0; /* lock game in hash as draw*/ R-=i/FAC; /*** total captd material ***/ Fifty = t|p<3?0:Fifty+1; + if(centr[p]==5)b[257+y]-=5; sp=ps; return l;} /* & not in check, signal */ v=m; /* (prevent fail-lows on */ } /* K-capt. replies) */ - J=f;Z=g; - SHAMAX( pl[k]+=!!t; ) - b[G]=b[FF];b[FF]=b[y]=0;b[x]=u;b[H]=t; /* undo move,G can be dummy */ + SHAMAX( pl[k]+=!!t; ) pl[t&31]+=!!t; + b[G]=rk;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 */ + s=t&&2&~rg|~t&16^k;v=r^flag>>12; /* platform & toggled vector*/ if(flag&15^4|u&32|| /* no double or moved before*/ - p>2&& /* no P & no lateral K move,*/ + p>2&!(flag&S)&& /* no P & no virgin jump, */ ((b[G=r<0?x&~15:BW-1|x&112]^32)<33 /* no virgin R in corner G, */ ||b[G^1]|b[G^2]|b[FF=y+v-r]) /* no 2 empty sq. next to R */ )t+=flag&4; /* fake capt. for nonsliding*/ - else F=y; /* enable e.p. */ - if(s&&flag&8)t=0,flag^=flag>>4&15; /* hoppers go to next phase */ - if(!(flag&S)) /* zig-zag piece? */ + else if(flag&64)t=flag&128?0:t,flag&=63;else F=y; /* enable e.p. */ + if(s&&flag&8&&!(y=rg&1?y-r:y,t=0) /* hoppers go to next phase */ + ||!(flag&S)&&!rg--) /* zig-zag piece? (w. delay)*/ r=v,flag^=flag>>4&15; /* alternate vector & mode */ }W(!t); /* if not capt. continue ray*/ }} @@ -300,7 +331,7 @@ if(z&4*S)K=X,L=Y&~S; int PrintResult(int s) { - int i, j, k, cnt=0; + int j, k, cnt=0; /* search last 50 states with this stm for third repeat */ for(j=2; j<=100 && j <= HistPtr; j+=2) @@ -341,11 +372,15 @@ int PrintResult(int s) if(cnt==-I+1) { if (s == WHITE) printf("0-1 {Black mates}\n"); - else + else { + if(succession) { // suppress loss claim if black might be able to replace its King by promotion + for(j=0;j=100) { + if(Fifty >= 2*drawMoves) { printf("1/2-1/2 {Draw by fifty move rule}\n"); return 4; } @@ -353,32 +388,42 @@ int PrintResult(int s) } -InitEngine() +void InitEngine() { - int i, j; - N=32*S+7;W(N-->S+3)T[N]=rand()>>9; srand(GetTickCount()); } -InitGame() +void InitGame() { - int i,j; + int i,k=0; + Side = WHITE; Q=0; O=S; + Fifty = 0; R = 0; for(i=0;i<16*BH;i++)b[i]=0; + for(i=0;i<32;i++)pl[i]=0; K=BW;W(K--) - {b[K]=oo[K+16]+16;b[K+112]=oo[K];b[K+16]=18;b[K+96]=1; /* initial board setup*/ - L=8;W(L--)b[16*L+K+257]=(K-BW/2)*(K-BW/2)+(L-3.5)*(L-3.5); /* center-pts table */ + {b[K]=oo[K+16]+16;b[K+112]=oo[K];b[K+16+16*!!makruk]=18;b[K+96-16*!!makruk]=1; /* initial board setup*/ + pl[oo[K+16]+16]++;pl[oo[K]]++;pl[18]++;pl[1]++; + if(w[oo[K+16]+16] == -1)pl[oo[K+16]+16]=1; + if(w[oo[K]] == -1)pl[oo[K]]=1; + L=8;W(L--)b[16*L+K+257]=(K-BW/2+hill/2.)*(K-BW/2+hill/2.)+(L-3.5)*(L-3.5); /* center-pts table */ } /*(in unused half b[])*/ - Side = WHITE; Q=0; O=S; - Fifty = 0; R = 0; - for(i=0; i12 || BH!=8) { printf("telluser unsupported board size %dx%d\n",BW,BH); exit(0); } + makruk = 0; if(fscanf(f, "=%d", &i)) makruk=67-i; // new method to indicate deviant zone depth (for now assumes 3) for(i=0; i='a'; blacktype[c&31]=i; piecename[i]=c&31; if(piecetype[c&31]==0) piecetype[c&31]=i; // only first + succession |= w[i] < -4; // expendable royalty; assume we can promote to it } 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]); /**/ c=0; if(i>15 || j>255) break; } + sh = w[7] < 250 ? 3 : 0; hill = (w[3] == -2); + 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; i 1 && !strcmp(argv[1], "-v")) argc++, argv--, printf("%s\n", VERSION), exit(0); if(argc>1 && sscanf(argv[1], "%d", &m)==1) { U = (1<TimeLeft/15) tlim = TimeLeft/15; PromPiece = 0; /* Always promote to Queen ourselves */ + for(N=K=0;K4,R=4;if(!(N&S-2))centr[3]=5,Z+=R>4,R=4;} +printf("# %d+%d pieces, centr = (%d,%d) R=%d\n", N&63, N>>7, centr[3], centr[4], R); N=0;K=I; + if(hill) centr[3] = R>20 ? 1 : 22-R; if (D(Side,-I,I,Q,O,LL|S,3)==I) { Side ^= BLACK^WHITE; - if(UnderProm>=0 && UnderProm != L) - { printf("tellics I hate under-promotions!\n"); - printf("resign { underpromotion } \n"); - Computer = EMPTY; - continue; - } else UnderProm = -1; + m = GetTickCount() - Ticks; + printf("# times @ %u: real=%d cpu=%1.0f\n", m + Ticks, m, + (CPUtime() - cpuT)/CLOCKS_PER_SEC); +printf("# promo = %d (%c) GT = %d\n", prom, prom + '`', GT); printf("move "); printf("%c%c%c%c",'a'+(K&15),'0'+BH-(K>>4), 'a'+(L&15),'0'+BH-(L>>4)); - if(prom)printf("%c",piecename[prom&15]+'a'-1); + if(prom)printf("%c",piecename[prom]+'a'-1); printf("\n"); - m = GetTickCount() - Ticks; /* time-control accounting */ TimeLeft -= m; @@ -558,7 +632,7 @@ int main(int argc, char **argv) continue; } if (!fgets(line, 256, stdin)) - return; + return 1; if (line[0] == '\n') continue; sscanf(line, "%s", command); @@ -567,9 +641,9 @@ int main(int argc, char **argv) if (!strcmp(command, "protover")) { printf("feature myname=\"" NAME " " VERSION "\"\n"); printf("feature memory=1\n"); - printf("feature setboard=0 ping=1 done=0\n"); + printf("feature setboard=0 xedit=1 ping=1 done=0\n"); printf("feature variants=\""); - PrintVariants(); + PrintVariants(0); printf("\"\n"); PrintOptions(); continue; @@ -610,7 +684,7 @@ int main(int argc, char **argv) } if (!strcmp(command, "quit")) /* exit engine */ - return; + return 0; if (!strcmp(command, "force")) { /* computer plays neither */ Computer = EMPTY; @@ -691,8 +765,12 @@ int main(int argc, char **argv) if(sscanf(line+7, "Ini File=%s", filename) == 1) { inifile = filename; continue; } - if(sscanf(line+7, "Clear Hash") == 1) for(i=0; iK = 0; + if(sscanf(line+7, "Clear Hash%c", &c) == 1) for(i=0; i<=U; i++) A->K = 0; + if(sscanf(line+7, "Info%c", &c) == 1) printf("telluser %s\n", info+3); 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, "Makruk rules=%s", Cambodian) == 1) continue; + if(sscanf(line+7, "Claim draw after=%d", &drawMoves) == 1) continue; continue; } if (!strcmp(command, "go")) { @@ -728,9 +806,9 @@ int main(int argc, char **argv) InitGame(); if(Setup) { for(i=0; i<128; i++) b[i] = setupPosition[i]; + for(i=0; i<32; i++) pl[i] = setupPosition[i+130]; Side = setupPosition[128]; Q = SetupQ; - pl[WHITE] = setupPosition[129]; - pl[BLACK] = setupPosition[130]; + R = setupPosition[129]; } for(i=0; i<=U; i++) A[i].D = A[i].K = 0; // clear hash table for(nr=0; nr= 'A' && m <= 'Z' && piecetype[m&31] - && line[1] >= 'a' && line[1] <= 'a'+BW-1 + if( m >= 'A' && m <= 'Z' && piecetype[m&31]) { + p = (color == WHITE ? piecetype : blacktype)[line[0]&31]; + if(line[1] == '@') { // stuff holdings + pl[color+p+5] = m = line[2] - '0'; + pl[BLACK+WHITE-color]+=m;pl[p+color]+=m; + Q+=m*w[p]; R+=m*(w[p]/FAC); + continue; + } else + if(line[1] >= 'a' && line[1] <= 'a'+BW-1 && line[2] >= '1' && line[2] <= '0'+BH) { - m = line[1]-16*line[2]+799; - switch(p = (color == WHITE ? piecetype : blacktype)[line[0]&31]) + 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 - if(w[p]<0) { // Royal piece on original square: virgin - if(color==BLACK && m<0x10 && p==oo[m+16] || - color==WHITE && m>0x6F && p==oo[m-0x70]) b[m] -= 32; - } else { Q+=w[p]; R+=w[p]/FAC; } - if((m==0x00 || m==BW-1 ) && color==BLACK && p==oo[m+16] || - (m==0x70 || m==0x6F+BW) && color==WHITE && p==oo[m-0x70]) - b[m] &= ~32; // corner piece as in original setup: virgin + if(color==BLACK && m<0x10 && p==oo[m+16] || // but make virgin on original square + color==WHITE && m>0x6F && p==oo[m-0x70]) b[m] -= 32; + if(w[p]<0) { // Royal piece on original square: virgin + Q-=w[p]; // assume value was flipped to indicate royalty + if(pl[p+color])R-=w[p]/FAC; // capturable King, add to material + } else { Q+=w[p]; R+=w[p]/FAC; } case 0: // undefined piece, ignore break; } - pl[BLACK+WHITE-color]++; + pl[BLACK+WHITE-color]++;pl[p+color]++; + if(w[p+color] == -1)pl[p+color]=1; // fake we have one if value = -1, to thwart extinction condition continue; + } } } if(Side != color) Q = -Q; GamePtr = HistPtr = 0; Setup = 1; SetupQ = Q; // start anew for(i=0; i<128; i++) setupPosition[i] = b[i]; // remember position setupPosition[128] = Side; - setupPosition[129] = pl[WHITE]; - setupPosition[130] = pl[BLACK]; + setupPosition[129] = R; + for(i=0; i<32; i++) setupPosition[i+130] = pl[i]; + Computer = EMPTY; // after edit: force mode! continue; } /* command not recognized, assume input move */ 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] = piecename[7]; - PromPiece = 7 - (Side == WHITE ? piecetype : blacktype)[line[4]&31]; - if(PromPiece == 7) PromPiece = 0; + if(line[4] == '\n') line[4] = 0; + 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) + if(w[GT&15] == -1 || w[GT&15]%10 == 3) L = S; // spoil move for promotion to King (or when marked non-promoting) + if (m & line[1] != '@') /* doesn't have move syntax */ printf("Error (unknown command): %s\n", command); - else if(D(Side,-I,I,Q,O,LL|S,3)!=I) { + 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) { /* 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; CopyBoard(HistPtr=HistPtr+1&1023); if(PrintResult(Side)) Computer = EMPTY; + } + } } + return 0; }