/*****************************************************************/\r
\r
#define MULTIPATH\r
-#define VERSION "4.8Q"\r
+#define VERSION "4.8S"\r
\r
#include <stdio.h>\r
#include <stdlib.h>\r
\r
#ifdef WIN32 \r
# include <windows.h>\r
+# define CPUtime 1000.*clock\r
#else\r
# include <sys/time.h>\r
+# include <sys/times.h>\r
+# include <unistd.h>\r
int GetTickCount() // with thanks to Tord\r
{ struct timeval t;\r
gettimeofday(&t, NULL);\r
return t.tv_sec*1000 + t.tv_usec/1000;\r
}\r
+ double CPUtime()\r
+ { // get CPU time used by process, converted to 'MILLICLOCKS'\r
+ struct tms cpuTimes;\r
+ static int cps = 0;\r
+ if(!cps) cps = sysconf(_SC_CLK_TCK);\r
+ times(&cpuTimes);\r
+ return ((double)(cpuTimes.tms_utime + cpuTimes.tms_stime) * CLOCKS_PER_SEC * 1000)/cps;\r
+ }\r
#endif\r
\r
int StartKey;\r
#else\r
# define FAC 128\r
# define EG 10\r
-# define NAME "Fairy-Max"\r
+# define NAME "Pair-o-Max"\r
# define SHAMAX(x)\r
# define FMAX(x) x\r
#endif\r
\r
/* make unique integer from engine move representation */\r
-#define PACK_MOVE 256*K + L + (PromPiece << 16);\r
+#define PACK_MOVE 256*K + L + (PromPiece << 16) + (GT<<24);\r
\r
/* convert intger argument back to engine move representation */\r
-#define UNPACK_MOVE(A) K = (A)>>8 & 255; L = (A) & 255; PromPiece = (A)>>16 & 255;\r
+#define UNPACK_MOVE(A) K = (A)>>8 & 255; L = (A) & 255; PromPiece = (A)>>16 & 255; GT = (A)>>24 & 255;\r
\r
/* Global variables visible to engine. Normally they */\r
/* would be replaced by the names under which these */\r
int MaxDepth;\r
int Post;\r
int Fifty;\r
-int UnderProm;\r
int GameNr;\r
int Resign;\r
+int Cambodian;\r
int Threshold = 800;\r
int Score;\r
int makruk;\r
-int prom, pm, gating;\r
+int prom, pm, gating, succession;\r
char piecename[32], piecetype[32], blacktype[32];\r
char selectedFairy[80];\r
char *inifile = INI_FILE;\r
\r
int M=136,S=128,I=8e3,Q,O,K,N,j,R,J,Z,LL,GT, /* M=0x88 */\r
BW,BH,sh,\r
-w[16]={0,2,2,-1,7,8,12,23,7,5}, /* relative piece values */\r
+w[32]={0,2,2,-1,7,8,12,23,7,5}, /* relative piece values */\r
o[256],\r
oo[32], /* initial piece setup */\r
of[256],\r
od[16]; /* 1st dir. in o[] per piece*/\r
\r
-signed char L,pl[32],\r
+signed char L,pl[32],pb[32],\r
b[513], /* board: 16x8+dummy, + PST */\r
T[4104], /* hash translation table */\r
centr[32],\r
int pv[10000],*sp=pv; // triangular array\r
int margin;\r
\r
-pboard()\r
+void pboard()\r
{int i;\r
i=-1;W(++i<128)printf(" %c",(i&15)==BW&&(i+=15-BW)?10:n[b[i]&31]);\r
}\r
\r
\r
-D(k,q,l,e,E,z,n) /* recursive minimax search, k=moving side, n=depth*/\r
-int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/\r
+D(k,q,l,e,ev,E,z,n) /* recursive minimax search, k=moving side, n=depth*/\r
+int k,q,l,e,ev,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/\r
{ /* e=score, z=prev.dest; J,Z=hashkeys; return score*/\r
- int j,r,m,v,d,h,i,F,G,P,V,f=J,g=Z,C,s,flag,FF,*ps=sp,kk=S;\r
+ 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;\r
signed char t,p,u,x,y,X,Y,H,B,gt;\r
- struct _*a=A+(J+(k+S)*E&U-1); /* lookup pos. in hash table*/\r
+ struct _*a=A+(J+(k+S)*E&U); /* lookup pos. in hash table*/\r
*sp++=0;\r
- q-=q<e;l-=l<=e; /* adj. window: delay bonus */\r
+ q-=q<ev;l-=l<=ev; /* adj. window: delay bonus */\r
d=a->D;m=a->V;X=a->F;Y=a->Y; /* resume at stored depth */\r
if(a->K-Z|z&S | /* miss: other pos. or empty*/\r
!(m<=q|X&8&&m>=l|X&S)) /* or window incompatible */\r
(K=X,L=Y&~S,Score=m,d=3))) /* time's up: go do best */\r
{x=B=X; /* start scan at prev. best */\r
h=Y&S; /* request try noncastl. 1st*/\r
- P=d>2&&l+I?D(16-k,-l,1-l,-e,2*S,2*S,d-3):I; /* search null move */\r
- m=-P<l|R<5?d-2?-I:e:-P; /*** prune if > beta unconsidered:static eval */\r
+ P=d>2&&l+I?D(16-k,-l,1-l,-e,-ev,2*S,2*S,d-3):I; /* search null move */\r
+ m=-P<l|R<5?d-2?-I:ev:-P; /*** prune if > beta unconsidered:static eval */\r
SHAMAX( if(pl[k]<=1&pl[16-k]>1)m=I-1; ) /* bare king loses */\r
N++; /* node count (for timing) */\r
do{u=b[x]; /* scan board looking for */\r
}\r
#endif\r
m=E<16|(E^112)<16&&flag&1&y-E<2&E-y<2?I:m; /* bad castling */\r
- if(p<3&y==E)H=z&127; /* shift capt.sqr. H if e.p.*/\r
+ if(p<3&y==E&flag)H=z&127; /* shift capt.sqr. H if e.p.*/\r
t=b[H];\r
if(flag&1+!t) /* mode (capt/nonc) allowed?*/\r
{if(t&&(t&16)==k)break; /* capture own */\r
if(i<0&&(pl[t&31]<2|| /* K capture, (of last K), */\r
t>>3&kk!=H&kk!=S||(kk=H,i=-i,0)))m=I,d=98;/* or duple check: cutoff*/\r
if(m>=l&d>1)goto C; /* abort on fail high */\r
- v=d-1?e:i-p; /*** MVV/LVA scoring if d=1**/\r
+ v=d-1?ev:i-p; /*** MVV/LVA scoring if d=1**/\r
if(d-!t>1) /*** all captures if d=2 ***/\r
{v=gt=0;G: /* retry move with gating */\r
v+=centr[p]?b[x+257]-b[y+257]:0; /* center positional pts. */\r
if(!(G&S))b[FF]=b[G],v+=50; /* castling: put R & score */\r
b[G]=b[H]=0;b[x]=gt;b[y]=u|32; /* do move, set non-virgin */\r
- pl[t&31]-=!!t; /* updat victim piece count */\r
+ i+=-((pl[t&31]-=!!t)&1)&pb[t&31];/* update piece count, pair bonus */\r
v-=w[p]>0|R<EG?0:20; /*** freeze K in mid-game ***/\r
if(p<3) /* pawns: */\r
{v-=9*((x-2&M||b[x-2]-u)+ /* structure, undefended */\r
i+=V; /* promotion / passer bonus */\r
} if(z&S && GamePtr<6) v+=(rand()>>10&31)-16;\r
J+=J(0);Z+=J(4)+G-S;\r
- SHAMAX( pl[k]-=!!t; ) /* count pieces per side */\r
+ pl[k]-=!!t; /* count pieces per side */\r
v+=e+i;V=m>q?m:q; /*** new eval & alpha ****/\r
+ re=v>>Fac(v>>15&16^k); /* Reduce eval if drawish for leading side */\r
if(z&S)V=m-margin>q?m-margin:q; /* multiPV */\r
C=d-1-(d>5&p>2&!t&!h); /* nw depth, reduce non-cpt.*/\r
C=R<EG|P-I|d<3||t&&p-3?C:d; /* extend 1 ply if in-check */\r
do\r
- s=C>2|v>V?-D(16-k,-l,-V,-v,/*** futility, recursive eval. of reply */\r
- F,y&255,C):v;\r
+ s=C>2|re>V?-D(16-k,-l,-V,/*** futility, recursive eval. of reply */\r
+ -v,-re,F,y&255,C):re;\r
W(s>q&++C<d); v=s; /* no fail:re-srch unreduced*/\r
if(v>V&v<l){int *p=sp;\r
sp=ps+1;\r
{if(v+I&&x==K&y==L>==GT) /* if move found */\r
{Q=-e-i;O=F;LL=L;prom=gt;\r
if(b[y]-u&15)prom=b[y]-=PromPiece, /* under-promotion, correct */\r
- J+=PromPiece; /* piece & invalidate hash */\r
+ pl[u&31]--,pl[prom&31]++,Z+=PromPiece;/*piece & invalidate hash */\r
a->D=99;a->V=0; /* lock game in hash as draw*/\r
R-=i/FAC; /*** total captd material ***/\r
Fifty = t|p<3?0:Fifty+1;\r
return l;} /* & not in check, signal */\r
v=m; /* (prevent fail-lows on */\r
} /* K-capt. replies) */\r
- SHAMAX( pl[k]+=!!t; ) pl[t&31]+=!!t;\r
+ pl[k]+=!!t;pl[t&31]+=!!t;\r
b[G]=b[FF];b[FF]=b[y]=0;b[x]=u;b[H]=t; /* undo move,G can be dummy */\r
} /* if non-castling */\r
if(z&S&&K==I&d>2&v>V&v<l){int *p=ps;char X,Y;\r
} /* encoded in X S,8 bits */\r
if(z&4*S)K=X,L=Y&~S;\r
sp=ps;\r
- return m+=m<e; /* delayed-loss bonus */\r
+ return m+=m<ev; /* delayed-loss bonus */\r
}\r
\r
+Fac(int k)\r
+{/* if mating potential in jeopardy, indicate score reduction (as shift) */\r
+ int m,h,i,j,e,f=0,r=0,n=pl[k+1]+pl[k+2]; /* k indicates strong side */\r
+ if(n<2){ /* less than 2 pawns */\r
+ r=1-n; /* reduce by 2 if no pawns */\r
+ m=pl[16-k]-n; /* my pieces (incl. King) */\r
+ if(m<4){ /* we have at most 2 pieces */\r
+ h=pl[k]-pl[17-k]-pl[18-k]; /* his pieces (incl. King) */\r
+ if(h<2)r=0; /* bare K easy even w.o. P */\r
+ j=h-n; /* defenders after sac for P*/\r
+ if(j<3&&j--){ /* can sac, <= 1 piece left */\r
+ i=18-k;W(!pl[++i]); /* get lowest piece */\r
+ e=abs(w[i--])*n; /* sac for Pawn (if any) */\r
+ W(h>1)h-=pl[++i],e-=pl[i]*w[i]; /* total value his remaining*/\r
+ if(!h)e+=3*w[i]; /* dual King, correct w[]<0 */\r
+ j&=pb[i]==-1; /* tough defenders left */\r
+ for(i=k+3,h=m;h>1;h-=pl[i++])e+=pl[i]*w[i],/* lead in piece material */\r
+ f|=pl[i]&pb[i]/*,printf("%d,%d,%d=%d,%d ",i,pl[i],pb[i],e,f)*/; /* detect mating minors */\r
+ if(!f&&e<350 /* non-mating minor ahead */\r
+ ||m-1&(pb[--i]>3|j) /* single color-bound or vs tough */\r
+ ||pl[i]==2&pb[i]<-1)r=3-n; /* non-mating pair */\r
+ }}}\r
+ return r;\r
+}\r
\r
/* Generic main() for Winboard-compatible engine */\r
/* (Inspired by TSCP) */\r
\r
int PrintResult(int s)\r
{\r
- int i, j, k, cnt=0;\r
+ int j, k, cnt=0;\r
\r
/* search last 50 states with this stm for third repeat */\r
for(j=2; j<=100 && j <= HistPtr; j+=2)\r
differs: ;\r
}\r
K=I;\r
- cnt = D(s,-I,I,Q,O,LL|4*S,3);\r
+ cnt = D(s,-I,I,Q,Q,O,LL|4*S,3);\r
#ifdef SHATRANJ\r
if(pl[s]==1 && pl[16-s]==1) {\r
printf("1/2-1/2 {Insufficient mating material}\n");\r
if(cnt==-I+1) {\r
if (s == WHITE)\r
printf("0-1 {Black mates}\n");\r
- else\r
+ else {\r
+ if(succession) { // suppress loss claim if black might be able to replace its King by promotion\r
+ for(j=0;j<BW;j++)if((b[j+96]&31)==18)return 0;\r
+ }\r
printf("1-0 {White mates}\n");\r
+ }\r
return 3;\r
}\r
if(Fifty >=100) {\r
}\r
\r
\r
-InitEngine()\r
+void InitEngine()\r
{\r
- int i, j;\r
-\r
N=32*S+7;W(N-->S+3)T[N]=rand()>>9;\r
srand(GetTickCount());\r
}\r
\r
-InitGame()\r
+void InitGame()\r
{\r
- int i,j,k=0;\r
+ int i,k=0;\r
\r
Side = WHITE; Q=0; O=S;\r
Fifty = 0; R = 0;\r
for(i=0; i<BW; i++) {\r
R += abs(w[oo[i]])/FAC + abs(w[oo[i+16]])/FAC;\r
Q += abs(w[oo[i]]) - abs(w[oo[i+16]]) + w[1] - w[2];\r
+ Q += (pl[i]>>1)*pb[i] -(pl[i+16]>>1)*pb[i];\r
if(w[oo[i]] < 0) k = w[oo[i]];\r
}\r
R -= 2*(-k/FAC);\r
- UnderProm = -1; pl[WHITE] = pl[BLACK] = 2*BW; \r
+ pl[WHITE] = pl[BLACK] = 2*BW; \r
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.\r
if(gating) pl[14] = pl[15] = pl[30] = pl[31] = 1, R += 2*(w[9]/FAC + w[10]/FAC);\r
}\r
\r
void CopyBoard(int s)\r
{\r
- int i, j, k, cnt=0;\r
+ int i, j;\r
\r
/* copy game representation of engine to HistoryBoard */\r
/* don't forget castling rights and e.p. state! */\r
\r
void PrintVariants(int combo)\r
{\r
- int i, j, count=0, total=0; char c=EOF+1, buf[80];\r
+ int count=0, total=0; char c=EOF+1, buf[80];\r
FILE *f;\r
\r
f = fopen(INI_FILE, "r");\r
printf("feature option=\"Ini File -file %s\"\n", inifile);\r
printf("feature option=\"Multi-PV Margin -spin %d 0 1000\"\n", margin);\r
printf("feature option=\"Variant fairy selects -combo "); PrintVariants(1); printf("\"\n");\r
+ printf("feature option=\"Cambodian Makruk rules -check %d\"\n", Cambodian);\r
printf("feature option=\"Dummy Slider Example -slider 20 0 100\"\n");\r
printf("feature option=\"Dummy String Example -string happy birthday!\"\n");\r
printf("feature option=\"Dummy Path Example -path .\"\n");\r
printf("feature done=1\n");\r
}\r
\r
-int LoadGame(char *name)\r
+void LoadGame(char *name)\r
{\r
int i, j, ptc, count=0; char c, buf[80], pieceToChar[80];\r
static int currentVariant;\r
\r
f = fopen(inifile, "r");\r
if(f==NULL)\r
- { printf("telluser piece-desription file '%s' not found\n", inifile);\r
+ { printf("telluser piece-description file '%s' not found\n", inifile);\r
exit(0);\r
}\r
if(fscanf(f, "version 4.8(%c)", &c)!=1 || c != 'w')\r
{ printf("telluser incompatible fmax.ini file\n"); exit(0); }\r
\r
- gating = 0;\r
+ gating = succession = 0;\r
if(name != NULL)\r
{ /* search for game name in definition file */\r
+ if(!strcmp(name, "makruk") && Cambodian) name = "cambodian"; else\r
if(!strcmp(name, "fairy")) name = selectedFairy;\r
gating = !strcmp(name, "seirawan");\r
while((ptc=fscanf(f, "Game: %s # %s", buf, pieceToChar))==0 || strcmp(name, buf) ) {\r
while(fscanf(f, "%d,%x", o+j, of+j)==2 ||\r
fscanf(f,"%c:%d",&c, w+i+1)==2)\r
{ if(c)\r
- { od[++i]=j; centr[i] = c>='a';\r
+ { od[++i]=j; centr[i] = c>='a'; w[i+16] = w[i];\r
blacktype[c&31]=i; piecename[i]=c&31;\r
if(piecetype[c&31]==0) piecetype[c&31]=i; // only first\r
+ pb[i] = pb[i+16] = w[i]>>3 & ~3; // pair bonus, for now 1/8 of piece value, leave low bits for flag\r
+ succession |= w[i] < -4; // expendable royalty; assume we can promote to it\r
+ } else {\r
+ 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\r
+ if(!o[j]) pb[i] = pb[i+16] = of[j--]; // hand-set pair bonus kludges: 3 for mating minor, negative for non-mating pair.\r
}\r
j++; o[j]=0;\r
/* 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]); /**/\r
\r
int main(int argc, char **argv)\r
{\r
- int Computer, MaxTime, MaxMoves, TimeInc, sec, i, j;\r
- char line[256], command[256], c, cc;\r
+ int Computer, MaxTime, MaxMoves, TimeInc, sec, i;\r
+ char line[256], command[256], c;\r
int m, nr;\r
- FILE *f;\r
+ double cpuT;\r
\r
if(argc>1 && sscanf(argv[1], "%d", &m)==1)\r
{ U = (1<<m)-1; argc--; argv++; }\r
/* the game have to be done in this time. */\r
/* If MaxMoves=1 any leftover time is lost*/\r
Ticks = GetTickCount();\r
+ cpuT = CPUtime(); printf("# times @ %u\n", Ticks);\r
m = MovesLeft<=0 ? 40 : MovesLeft;\r
tlim = (0.6-0.06*(BW-8))*(TimeLeft+(m-1)*TimeInc)/(m+7);\r
if(tlim>TimeLeft/15) tlim = TimeLeft/15;\r
PromPiece = 0; /* Always promote to Queen ourselves */\r
N=0;K=I;\r
- if (D(Side,-I,I,Q,O,LL|S,3)==I) {\r
+ if (D(Side,-I,I,Q,Q,O,LL|S,3)==I) {\r
Side ^= BLACK^WHITE;\r
- if(UnderProm>=0 && UnderProm != L)\r
- { printf("tellics I hate under-promotions!\n");\r
- printf("resign { underpromotion } \n");\r
- Computer = EMPTY;\r
- continue;\r
- } else UnderProm = -1;\r
+ m = GetTickCount() - Ticks;\r
+ printf("# times @ %u: real=%d cpu=%1.0f\n", m + Ticks, m,\r
+ (CPUtime() - cpuT)/CLOCKS_PER_SEC);\r
printf("move ");\r
printf("%c%c%c%c",'a'+(K&15),'0'+BH-(K>>4),\r
'a'+(L&15),'0'+BH-(L>>4));\r
if(prom)printf("%c",piecename[prom&15]+'a'-1);\r
printf("\n");\r
- m = GetTickCount() - Ticks;\r
\r
/* time-control accounting */\r
TimeLeft -= m;\r
continue;\r
}\r
if (!fgets(line, 256, stdin))\r
- return;\r
+ return 1;\r
if (line[0] == '\n')\r
continue;\r
sscanf(line, "%s", command);\r
if (!strcmp(command, "protover")) {\r
printf("feature myname=\"" NAME " " VERSION "\"\n");\r
printf("feature memory=1\n");\r
- printf("feature setboard=0 ping=1 done=0\n");\r
+ printf("feature setboard=0 xedit=1 ping=1 done=0\n");\r
printf("feature variants=\"");\r
PrintVariants(0);\r
printf("\"\n");\r
}\r
if (!strcmp(command, "quit"))\r
/* exit engine */\r
- return;\r
+ return 0;\r
if (!strcmp(command, "force")) {\r
/* computer plays neither */\r
Computer = EMPTY;\r
if(sscanf(line+7, "Ini File=%s", filename) == 1) {\r
inifile = filename; continue;\r
}\r
- if(sscanf(line+7, "Clear Hash") == 1) for(i=0; i<U; i++) A->K = 0;\r
+ if(sscanf(line+7, "Clear Hash%c", &c) == 1) for(i=0; i<=U; i++) A->K = 0;\r
if(sscanf(line+7, "MultiVariation Margin=%d", &margin) == 1) continue;\r
if(sscanf(line+7, "Variant fairy selects=%s", selectedFairy+6) == 1) continue;\r
+ if(sscanf(line+7, "Cambodian Makruk rules=%d", &Cambodian) == 1) continue;\r
continue;\r
}\r
if (!strcmp(command, "go")) {\r
}\r
if (!strcmp(command, "hint")) {\r
Ticks = GetTickCount(); tlim = 1000;\r
- D(Side,-I,I,Q,O,LL|4*S,6);\r
+ D(Side,-I,I,Q,Q,O,LL|4*S,6);\r
if (K==0 && L==0)\r
continue;\r
printf("Hint: ");\r
for(i=0; i<=U; i++) A[i].D = A[i].K = 0; // clear hash table\r
for(nr=0; nr<GamePtr; nr++) {\r
UNPACK_MOVE(GameHistory[nr]);\r
- D(Side,-I,I,Q,O,LL|S,3);\r
+ D(Side,-I,I,Q,Q,O,LL|S,3);\r
Side ^= BLACK^WHITE;\r
}\r
continue;\r
continue;\r
}\r
if (!strcmp(command, "edit")) {\r
- int color = WHITE, p;\r
+ int color = WHITE, p, r;\r
\r
while(fgets(line, 256, stdin)) {\r
m = line[0];\r
Q = -Q;\r
continue;\r
}\r
- if( m >= 'A' && m <= 'Z' && piecetype[m&31]\r
- && line[1] >= 'a' && line[1] <= 'a'+BW-1\r
+ if( m >= 'A' && m <= 'Z' && piecetype[m&31]) {\r
+ p = (color == WHITE ? piecetype : blacktype)[line[0]&31];\r
+ if(line[1] == '@') { // stuff holdings\r
+ pl[color+p+5] = m = line[2] - '0';\r
+ pl[BLACK+WHITE-color]+=m;pl[p+color]+=m;\r
+ Q+=m*w[p]; R+=m*(w[p]/FAC);\r
+ continue;\r
+ } else\r
+ if(line[1] >= 'a' && line[1] <= 'a'+BW-1\r
&& line[2] >= '1' && line[2] <= '0'+BH) {\r
- m = line[1]-16*line[2]+799;\r
- switch(p = (color == WHITE ? piecetype : blacktype)[line[0]&31])\r
+ m = line[1]-16*line[2]+799; r = m & 0x70;\r
+ switch(p)\r
{\r
case 1:\r
case 2:\r
if(color==WHITE)\r
- b[m]=(m&0x70)==0x60?1:33,\r
- Q+=w[1];\r
- else b[m]=(m&0x70)==0x10?18:50,\r
- Q+=w[2];\r
+ b[m]=r==0x10?161:r==0x20?97:r==0x60?1:33,\r
+ Q+=w[1]+(r==0x10?S:r==0x20?64:0);\r
+ else b[m]=r==0x60?178:r==0x50?114:r==0x10?18:50,\r
+ Q+=w[2]+(r==0x60?S:r==0x50?64:0);\r
break;\r
default:\r
b[m]=p+color+32; // assume non-virgin\r
+ if(color==BLACK && m<0x10 && p==oo[m+16] || // but make virgin on original square\r
+ color==WHITE && m>0x6F && p==oo[m-0x70]) b[m] -= 32;\r
if(w[p]<0) { // Royal piece on original square: virgin\r
- if(color==BLACK && m<0x10 && p==oo[m+16] ||\r
- color==WHITE && m>0x6F && p==oo[m-0x70]) b[m] -= 32;\r
Q-=w[p]; // assume value was flipped to indicate royalty\r
if(pl[p+color])R-=w[p]/FAC; // capturable King, add to material\r
} else { Q+=w[p]; R+=w[p]/FAC; }\r
- if((m==0x00 || m==BW-1 ) && color==BLACK && p==oo[m+16] ||\r
- (m==0x70 || m==0x6F+BW) && color==WHITE && p==oo[m-0x70])\r
- b[m] &= ~32; // corner piece as in original setup: virgin\r
case 0: // undefined piece, ignore\r
break;\r
}\r
- pl[BLACK+WHITE-color]++;pl[p+color]++;\r
+ pl[BLACK+WHITE-color]++; if(pl[p+color]++&1) Q+=pb[p];\r
if(w[p+color] == -1)pl[p+color]=1; // fake we have one if value = -1, to thwart extinction condition\r
continue;\r
+ }\r
}\r
}\r
if(Side != color) Q = -Q;\r
GT = (Side == WHITE ? piecetype : blacktype)[line[4]&31];\r
if(GT) PromPiece = (Side == WHITE ? 7 : 7+pm) - GT, GT |= 32 + Side;\r
{char *c=line; K=c[0]-16*c[1]+799;L=c[2]-16*c[3]+799; }\r
- if (m)\r
+ if(w[GT&15] == -1) L = S; // spoil move for promotion to King\r
+ if (m & line[1] != '@')\r
/* doesn't have move syntax */\r
printf("Error (unknown command): %s\n", command);\r
else { int i=-1;\r
if(b[L] && (b[L]&16) == Side && w[b[L]&15] < 0) // capture own King: castling\r
{ i=K; K = L; L = i>L ? i-1 : i+2; }\r
- if(w[GT&15] < -1) pl[GT&31]++, J+=89729; // promotion to royal piece\r
- if(b[K]&32) GT = 0; // non-virgin mover => true promotion rather than gating\r
- if(D(Side,-I,I,Q,O,LL|S,3)!=I) {\r
+ if((b[K]&15) < 3) GT = 0; // Pawn => true promotion rather than gating\r
+ if(D(Side,-I,I,Q,Q,O,LL|S,3)!=I) {\r
/* did have move syntax, but illegal move */\r
printf("Illegal move:%s\n", line);\r
} else { /* legal move, perform it */\r