char fireMask;\r
} UndoInfo;\r
\r
-char *array, *reason;\r
+char *array, fenArray[4000], *reason;\r
int bWidth, bHeight, bsize, zone, currentVariant;\r
int stm, xstm, hashKeyH, hashKeyL, framePtr, msp, nonCapts, rootEval, retMSP, retFirst, retDep, pvPtr, level, cnt50, chuFlag=1, tenFlag, mobilityScore;\r
int nodes, startTime, tlim1, tlim2, repCnt, comp;\r
Move retMove, moveStack[10000], path[100], repStack[300], pv[1000], repeatMove[300];\r
\r
+ int maxDepth; // used by search\r
+\r
#define X 36 /* slider */\r
#define R 37 /* jump capture */\r
#define N -1 /* Knight */\r
for(i=0; ; i++) {\r
//printf("next rank: %s\n", array);\r
for(j = BW*i; ; j++) {\r
+ int pflag=0;\r
+ if(*array == '+') pflag++, array++;\r
c = name[0] = *array++;\r
if(!c) goto eos;\r
if(c == '.') continue;\r
if(name[1]) name[1] += 'A' - 'a';\r
} else color = WHITE;\r
p1 = LookUp(name, var);\r
+ if(!p1) printf("tellusererror Unknown piece '%s' in setup\n", name), exit(-1);\r
+ if(pflag && p1->promoted) p1 = LookUp(p1->promoted, var); // use promoted piece instead\r
n = AddPiece(color, p1);\r
p[n].pos = j;\r
- if(p1->promoted[0]) {\r
+ if(p1->promoted[0] && !pflag) {\r
p2 = LookUp(p1->promoted, var);\r
m = AddPiece(color, p2);\r
if(m <= n) n += 2;\r
p[EDGE].qval = 5; // tenjiku jump-capturer sentinel\r
}\r
\r
+int\r
+PSTest ()\r
+{\r
+ int r, f, score, tot=0;\r
+ for(r=0; r<BH; r++) for(f=0; f<BH; f++) {\r
+ int s = BW*r+f;\r
+ int piece = board[s];\r
+ if(!piece) continue;\r
+ score = p[piece].value + PST[p[piece].pst + s];\r
+ if(piece & 1) tot += score; else tot -= score;\r
+ }\r
+ return tot;\r
+}\r
+\r
int flag;\r
\r
inline int\r
#if 0\r
if(curEval >= beta) {\r
stm ^= WHITE;\r
- score = -Search(-beta, -iterAlpha, difEval, depth-3, promoSuppress & SQUARE, ABSENT);\r
+ score = -Search(-beta, -iterAlpha, -difEval, depth-3, promoSuppress & SQUARE, ABSENT);\r
stm ^= WHITE;\r
if(score >= beta) { msp = oldMSP; retDep += 3; return score + (score < curEval); }\r
}\r
if(promoSuppress & PROMOTE) score = -INF; // non-Lion captures Lion after opponent did same\r
defer |= PROMOTE; // if we started, flag he cannot do it in reply\r
}\r
- if(score == -INF) { moveStack[curMove] = 0; goto abortMove; } // zap illegal moves\r
+ if(score == -INF) {\r
+ if(level == 1) repeatMove[repCnt++] = move & 0xFFFFFF | (p[tb.piece].value == 10*LVAL ? 3<<24 : 1 << 24);\r
+ moveStack[curMove] = 0; // zap illegal moves\r
+ goto abortMove;\r
+ }\r
}\r
#if 1\r
score = -Search(-beta, -iterAlpha, -difEval - tb.booty, replyDep, promoSuppress & ~PROMOTE, defer);\r
int i; // WB thinking output\r
printf("%d %d %d %d", iterDep, bestScore, (GetTickCount() - startTime)/10, nodes);\r
for(i=0; pv[i]; i++) printf(" %s", MoveToText(pv[i], 0));\r
- printf("\n"); fflush(stdout);\r
+ if(iterDep == 1) printf(" { root eval = %4.2f dif = %4.2f; abs = %4.2f}", curEval/100., difEval/100., PSTest()/100.);\r
+ printf("\n");\r
+ fflush(stdout);\r
}\r
if(GetTickCount() - startTime > tlim1) break; // do not start iteration we can (most likely) not finish\r
}\r
#define INVALID 0\r
\r
// some parameter of your engine\r
- #define MAXMOVES 500 /* maximum game length */\r
- #define MAXPLY 60 /* maximum search depth */\r
+ #define MAXMOVES 2000 /* maximum game length */\r
+ #define MAXPLY 20 /* maximum search depth */\r
\r
#define OFF 0\r
#define ON 1\r
\r
-#define DEFAULT_FEN ""\r
-\r
typedef Move MOVE;\r
\r
int moveNr; // part of game state; incremented by MakeMove\r
sup2 = sup1; sup1 = sup0;\r
}\r
\r
+char fenNames[] = "RV....DKDEFL..DHGB......SMLNKN..FK....BT..VM..PH...."; // pairs of char\r
+char fenPromo[] = "WLDHSMSECPB R HFDE....WHFB..LNG ..DKVMFS..FO..FK...."; // pairs of char\r
+\r
+char *\r
+Convert (char *fen)\r
+{\r
+ char *p = fenArray, *q, *rows[36], tmp[4000];\r
+ int n=0;\r
+ printf("# convert FEN '%s'\n", fen);\r
+ q = strchr(fen, ' '); if(q) *q = 0; q = fen;\r
+ do { rows[n++] = q; q = strchr(q, '/'); if(!q) break; *q++ = 0; } while(1);\r
+ *tmp = 0;\r
+ while(--n >= 0) { strcat(tmp, rows[n]); if(n) strcat(tmp, "/"); }\r
+ fen = tmp;\r
+ printf("# flipped FEN '%s'\n", fen);\r
+ while(*fen) {\r
+ if(*fen == ' ') { *p = 0; break; }\r
+ if(n=atoi(fen)) fen++; // digits read\r
+ if(n > 9) fen++; // double digit\r
+ while(n-- > 0) *p++ = '.'; // expand to empty squares\r
+ if(isalpha(*fen)) {\r
+ char *table = fenNames;\r
+ n = *fen > 'Z' ? 'a' - 'A' : 0;\r
+ if(currentVariant == V_CHESS && *fen - 'A' - n == 'N' // In Chess N is Knight, not Lion\r
+ || table[2* (*fen - 'A' - n)] == '.') *p++ = *fen; else {\r
+ *p++ = ':';\r
+ *p++ = table[2* (*fen - 'A' - n)] + n;\r
+ *p++ = table[2* (*fen - 'A' - n)+1] + n;\r
+ }\r
+ } else *p++ = *fen;\r
+ fen++;\r
+ }\r
+ printf("# converted FEN '%s'\n", fenArray);\r
+ return fenArray;\r
+}\r
+\r
int\r
Setup2 (char *fen)\r
{\r
+ int stm = WHITE;\r
+ if(fen) {\r
+ char *q = strchr(fen, '\n');\r
+ if(q) *q = 0;\r
+ if(q = strchr(fen, ' ')) stm = (q[1] == 'b' ? BLACK : WHITE); // fen contains color field\r
+ if(strchr(fen, '.') || strchr(fen, ':')) array = fen; else array = Convert(fen);\r
+ }\r
SetUp(array, currentVariant);\r
sup0 = sup1 = sup2 = ABSENT;\r
- rootEval = cnt50 = hashKeyH = hashKeyL = 0;\r
- return WHITE;\r
+ rootEval = cnt50 = hashKeyH = hashKeyL = moveNr = 0;\r
+ return stm;\r
}\r
\r
void\r
if((moveStack[i] & (PROMOTE | DEFER-1)) == ret) break;\r
if((moveStack[i] & DEFER-1) == ret) deferred = i; // promoted version of entered non-promotion is legal\r
}\r
+printf("# moveNr = %d in {%d,%d}\n", i, retFirst, retMSP);\r
if(i>=retMSP) { // no exact match\r
if(deferred) { // but maybe non-sensical deferral\r
int flags = p[board[f]].promoFlag;\r
for(i=retFirst; i<retMSP; i++) printf("# %d. %08x %08x %s\n", i-50, moveStack[i], ret, MoveToText(moveStack[i], 0));\r
reason = NULL;\r
for(i=0; i<repCnt; i++) {if((repeatMove[i] & 0xFFFFFF) == ret) {\r
- reason = "Repeats earlier position";\r
+ if(repeatMove[i] & 1<<24) reason = (repeatMove[i] & 1<<25 ? "Distant capture of protected Lion" : "Counterstrike against Lion");\r
+ else reason = "Repeats earlier position";\r
break;\r
}\r
printf("# %d. %08x %08x %s\n", i, repeatMove[i], ret, MoveToText(repeatMove[i], 0));\r
int\r
SearchBestMove (int stm, int timeLeft, int mps, int timeControl, int inc, int timePerMove, MOVE *move, MOVE *ponderMove)\r
{\r
- int score, targetTime, movesLeft = 50;\r
+ int score, targetTime, movesLeft = BW*BH/4 + 20;\r
if(mps) movesLeft = mps - (moveNr>>1)%mps;\r
targetTime = timeLeft*10 / (movesLeft + 2) + 1000 * inc;\r
+ if(moveNr < 30) targetTime *= 0.5 + moveNr/60.; // speedup in opening\r
if(timePerMove > 0) targetTime = timeLeft * 5;\r
startTime = GetTickCount();\r
tlim1 = 0.2*targetTime;\r
nodes = 0;\r
MapFromScratch(attacks);\r
retMove = INVALID; repCnt = 0;\r
- score = Search(-INF-1, INF+1, rootEval, 20, sup1, sup2);\r
+ score = Search(-INF-1, INF+1, rootEval, maxDepth, sup1, sup2);\r
*move = retMove;\r
*ponderMove = INVALID;\r
return score;\r
int TakeBack(int n)\r
{ // reset the game and then replay it to the desired point\r
int last, stm;\r
- stm = Setup2(NULL);\r
+ Init(currentVariant); stm = Setup2(NULL);\r
printf("# setup done");fflush(stdout);\r
last = moveNr - n; if(last < 0) last = 0;\r
for(moveNr=0; moveNr<last; moveNr++) stm = MakeMove2(stm, gameMove[moveNr]),printf("make %2d: %x\n", moveNr, gameMove[moveNr]);\r
int engineSide=NONE; // side played by engine\r
int timeLeft; // timeleft on engine's clock\r
int mps, timeControl, inc, timePerMove; // time-control parameters, to be used by Search\r
- int maxDepth; // used by search\r
MOVE move, ponderMove;\r
int i, score;\r
char inBuf[8000], command[80];\r
\r
if(stm == engineSide) { // if it is the engine's turn to move, set it thinking, and let it move\r
\r
+pboard(board);\r
score = SearchBestMove(stm, timeLeft, mps, timeControl, inc, timePerMove, &move, &ponderMove);\r
\r
if(move == INVALID) { // game apparently ended\r
// wait for input, and read it until we have collected a complete line\r
for(i = 0; (inBuf[i] = getchar()) != '\n'; i++);\r
inBuf[i+1] = 0;\r
-pboard(board);\r
-pmoves(retFirst, retMSP);\r
\r
// extract the first word\r
sscanf(inBuf, "%s", command);\r
for(i=0; i<5; i++) {\r
sscanf(inBuf+8, "%s", command);\r
if(!strcmp(variants[i].name, command)) {\r
-printf("var %d\n",i);\r
Init(i); stm = Setup2(NULL); break;\r
}\r
}\r
if(!strcmp(command, "ping")) { printf("pong%s", inBuf+4); continue; }\r
// if(!strcmp(command, "")) { sscanf(inBuf, " %d", &); continue; }\r
if(!strcmp(command, "new")) {\r
- engineSide = BLACK; Init(V_CHESS); stm = Setup2(DEFAULT_FEN); maxDepth = MAXPLY; randomize = OFF; comp = 0;\r
+ engineSide = BLACK; Init(V_CHESS); stm = Setup2(NULL); maxDepth = MAXPLY; randomize = OFF; comp = 0;\r
continue;\r
}\r
- if(!strcmp(command, "setboard")){ engineSide = NONE; stm = Setup2(inBuf+9); continue; }\r
+ if(!strcmp(command, "setboard")){ engineSide = NONE; Init(currentVariant); stm = Setup2(inBuf+9); continue; }\r
if(!strcmp(command, "easy")) { ponder = OFF; continue; }\r
if(!strcmp(command, "hard")) { ponder = ON; continue; }\r
if(!strcmp(command, "undo")) { stm = TakeBack(1); continue; }\r
if(!strcmp(command, "")) { continue; }\r
if(!strcmp(command, "usermove")){\r
int move = ParseMove(inBuf+9);\r
+pboard(board);\r
if(move == INVALID) {\r
if(reason) printf("Illegal move {%s}\n", reason); else printf("%s\n", reason="Illegal move");\r
if(comp) PrintResult(stm, -INF); // against computer: claim\r