X-Git-Url: http://winboard.nl/cgi-bin?p=fairymax.git;a=blobdiff_plain;f=fairymax.c;h=f20bb1f536678ae6f55f3af2efedbc859105a161;hp=931099a579ca46d54f77227b4e7828a93961712d;hb=d0e4774e9509e069ef252a071be2bdd497c810dd;hpb=5b64a22e62beb2c9d21d5567993eb0f74b1fa074 diff --git a/fairymax.c b/fairymax.c index 931099a..f20bb1f 100644 --- a/fairymax.c +++ b/fairymax.c @@ -18,7 +18,7 @@ /*****************************************************************/ #define MULTIPATH -#define VERSION "4.8R" +#define VERSION "4.8T" #include #include @@ -98,14 +98,13 @@ int MovesLeft; int MaxDepth; int Post; int Fifty; -int UnderProm; int GameNr; int Resign; -int Cambodian; +char Cambodian[80] = "makruk"; int Threshold = 800; int Score; int makruk; -int prom, pm, gating; +int prom, pm, gating, succession; char piecename[32], piecetype[32], blacktype[32]; char selectedFairy[80]; char *inifile = INI_FILE; @@ -140,7 +139,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]); } @@ -150,8 +149,8 @@ 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,gt; - struct _*a=A+(J+(k+S)*E&U-1); /* lookup pos. in hash table*/ + 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 */ @@ -175,7 +174,7 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ 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 */ @@ -188,7 +187,7 @@ 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 */ @@ -200,7 +199,7 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ 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 */ + 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|Rq?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; @@ -232,8 +231,9 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ if(z&S&&K-I) /* move pending: check legal*/ {if(v+I&&x==K&y==L>==GT) /* if move found */ {Q=-e-i;O=F;LL=L;prom=gt; - if(b[y]-u&15)prom=b[y]-=PromPiece, /* under-promotion, correct */ - Z+=PromPiece; /* piece & invalidate hash */ + 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; @@ -242,7 +242,7 @@ int k,q,l,e,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/ v=m; /* (prevent fail-lows on */ } /* K-capt. replies) */ 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 */ + 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&&K==I&d>2&v>V&v>4&15; /* hoppers go to next phase */ - if(!(flag&S)) /* zig-zag piece? */ + if(--rg<0&!(flag&S)) /* zig-zag piece? (w. delay)*/ r=v,flag^=flag>>4&15; /* alternate vector & mode */ }W(!t); /* if not capt. continue ray*/ }} @@ -324,7 +324,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) @@ -342,6 +342,11 @@ int PrintResult(int s) } differs: ; } + + + + + K=I; cnt = D(s,-I,I,Q,O,LL|4*S,3); #ifdef SHATRANJ @@ -365,8 +370,12 @@ 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) { @@ -377,17 +386,15 @@ 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,k=0; + int i,k=0; Side = WHITE; Q=0; O=S; Fifty = 0; R = 0; @@ -406,14 +413,14 @@ InitGame() if(w[oo[i]] < 0) k = w[oo[i]]; } R -= 2*(-k/FAC); - UnderProm = -1; pl[WHITE] = pl[BLACK] = 2*BW; + 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[14] = pl[15] = pl[30] = pl[31] = 1, R += 2*(w[9]/FAC + w[10]/FAC); } void CopyBoard(int s) { - int i, j, k, cnt=0; + int i, j; /* copy game representation of engine to HistoryBoard */ /* don't forget castling rights and e.p. state! */ @@ -424,7 +431,7 @@ void CopyBoard(int s) void PrintVariants(int combo) { - int i, j, count=0, total=0; char c=EOF+1, buf[80]; + int count=0, total=0; char c=EOF+1, buf[80]; FILE *f; f = fopen(INI_FILE, "r"); @@ -436,7 +443,7 @@ void PrintVariants(int combo) while((c = fgetc(f)) != EOF && c != '\n'); if(c == EOF) break; total++; - if(combo == (strstr(buf, "fairy/") != buf)) continue; + if(*buf < 'a' || combo == (strstr(buf, "fairy/") != buf)) continue; if(combo && count == 0) strcpy(selectedFairy, buf); if(count++) printf(combo ? " /// " : ","); printf("%s", combo ? buf+6 : buf); @@ -453,7 +460,7 @@ void PrintOptions() printf("feature option=\"Ini File -file %s\"\n", inifile); printf("feature option=\"Multi-PV Margin -spin %d 0 1000\"\n", margin); printf("feature option=\"Variant fairy selects -combo "); PrintVariants(1); printf("\"\n"); - printf("feature option=\"Cambodian Makruk rules -check %d\"\n", Cambodian); + printf("feature option=\"Makruk rules -combo makruk /// Cambodian /// Ai-wok\"\n"); printf("feature option=\"Dummy Slider Example -slider 20 0 100\"\n"); printf("feature option=\"Dummy String Example -string happy birthday!\"\n"); printf("feature option=\"Dummy Path Example -path .\"\n"); @@ -461,27 +468,27 @@ void PrintOptions() printf("feature done=1\n"); } -int LoadGame(char *name) +void LoadGame(char *name) { - int i, j, ptc, count=0; char c, buf[80], pieceToChar[80]; + int i, j, ptc=0, count=0; char c, buf[80], pieceToChar[80], parent[80]; static int currentVariant; FILE *f; f = fopen(inifile, "r"); if(f==NULL) - { printf("telluser piece-desription file '%s' not found\n", inifile); + { printf("telluser piece-description file '%s' not found\n", inifile); exit(0); } if(fscanf(f, "version 4.8(%c)", &c)!=1 || c != 'w') { printf("telluser incompatible fmax.ini file\n"); exit(0); } - gating = 0; + gating = succession = 0; if(name != NULL) { /* search for game name in definition file */ - if(!strcmp(name, "makruk") && Cambodian) name = "cambodian"; else + if(!strcmp(name, "makruk")) 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) { @@ -496,6 +503,7 @@ int LoadGame(char *name) /* We have found variant, or if none specified, are at beginning of file */ if(fscanf(f, "%dx%d", &BW, &BH)!=2 || BW>12 || BH!=8) { printf("telluser unsupported board size %dx%d\n",BW,BH); exit(0); } + makruk = 0; if(fscanf(f, "=%d", &i)) makruk=64; // 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]); /**/ @@ -518,24 +527,25 @@ int 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; i1 && sscanf(argv[1], "%d", &m)==1) { U = (1<=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("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"); /* time-control accounting */ @@ -614,7 +618,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); @@ -666,7 +670,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; @@ -747,10 +751,10 @@ 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, "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; + if(sscanf(line+7, "Makruk rules=%s", Cambodian) == 1) continue; continue; } if (!strcmp(command, "go")) { @@ -813,7 +817,7 @@ int main(int argc, char **argv) continue; } if (!strcmp(command, "edit")) { - int color = WHITE, p; + int color = WHITE, p, r; while(fgets(line, 256, stdin)) { m = line[0]; @@ -840,16 +844,16 @@ int main(int argc, char **argv) } else if(line[1] >= '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 @@ -884,7 +888,8 @@ int main(int argc, char **argv) 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) L = S; // spoil move for promotion to King + if (m & line[1] != '@') /* doesn't have move syntax */ printf("Error (unknown command): %s\n", command); else { int i=-1; @@ -902,6 +907,8 @@ int main(int argc, char **argv) CopyBoard(HistPtr=HistPtr+1&1023); if(PrintResult(Side)) Computer = EMPTY; } + } } + return 0; }