char fireMask;\r
} UndoInfo;\r
\r
-char *array;\r
+char *array, *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;\r
-Move retMove, moveStack[10000], path[100], repStack[300], pv[1000];\r
+int nodes, startTime, tlim1, tlim2, repCnt, comp;\r
+Move retMove, moveStack[10000], path[100], repStack[300], pv[1000], repeatMove[300];\r
\r
#define X 36 /* slider */\r
#define R 37 /* jump capture */\r
for(i=0; i<8; i++) { // scan all knight jumps to locate source\r
int x = sqr - nStep[i], attacker = board[x];\r
if(attacker == EMPTY || (attacker & TYPE) != stm) continue;\r
- if(p[attacker].range[i] <= N && p[attacker].range[i] >= S && p[attacker].range[i] != J) { // has Knight jump in our direction\r
+ if(p[attacker].range[i] <= L && p[attacker].range[i] >= S || p[attacker].range[i] == N) { // has Knight jump in our direction\r
NewCapture(x, sqr + victimValue, p[attacker].promoFlag); // plain jump (as in N)\r
if(p[attacker].range[i] < N) { // Lion power; generate double captures over two possible intermediates\r
int v = kStep[i]; // leftish path\r
if(flag & depth >= 0) printf("%2d:%d made %d/%d %s\n", depth, iterDep, curMove, msp, MoveToText(moveStack[curMove], 0));\r
for(i=2; i<=cnt50; i+=2) if(repStack[level-i+200] == hashKeyH) {\r
moveStack[curMove] = 0; // erase forbidden move\r
- score = -INF; goto repetition;\r
+ if(!level) repeatMove[repCnt++] = move & 0xFFFFFF; // remember outlawed move\r
+ score = -INF; moveStack[curMove] = 0; goto repetition;\r
}\r
repStack[level+200] = hashKeyH;\r
\r
if(*moveText == '+') ret |= PROMOTE;\r
printf("# suppress = %c%d\n", sup1%BW+'a', sup1/BW);\r
MapFromScratch(attacks);\r
- postThinking--;\r
+ postThinking--; repCnt = 0;\r
Search(-INF-1, INF+1, 0, 1, sup1 & ~PROMOTE, sup2);\r
postThinking++;\r
for(i=retFirst; i<retMSP; i++) {\r
if(!(flags & promoBoard[f])) moveStack[i] |= DEFER; // came from outside zone, so essential deferral\r
}\r
}\r
- if(i >= retMSP)\r
- for(i=retFirst; i<retMSP; i++) printf("# %d. %08x %08x %s\n", i-20, moveStack[i], ret, MoveToText(moveStack[i], 0));\r
+ if(i >= retMSP) {\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
+ break;\r
+ }\r
+ printf("# %d. %08x %08x %s\n", i, repeatMove[i], ret, MoveToText(repeatMove[i], 0));\r
+}\r
+ }\r
}\r
return (i >= retMSP ? INVALID : moveStack[i]);\r
}\r
//pmap(attacks, WHITE);\r
//pmap(attacks, BLACK);\r
//flag=1;\r
- postThinking--;\r
+ postThinking--; repCnt = 0;\r
Search(-INF-1, INF+1, 0, 1, sup1 & ~PROMOTE, sup2);\r
postThinking++;\r
flag=0;\r
tlim2 = 1.9*targetTime;\r
nodes = 0;\r
MapFromScratch(attacks);\r
- retMove = INVALID;\r
+ retMove = INVALID; repCnt = 0;\r
score = Search(-INF-1, INF+1, rootEval, 20, sup1, sup2);\r
*move = retMove;\r
*ponderMove = INVALID;\r
\r
void PrintResult(int stm, int score)\r
{\r
- if(score == 0) printf("1/2-1/2\n");\r
- if(score > 0 && stm == WHITE || score < 0 && stm == BLACK) printf("1-0\n");\r
- else printf("0-1\n");\r
+ char tail[100];\r
+ if(reason) sprintf(tail, " {%s}", reason); else *tail = 0;\r
+ if(score == 0) printf("1/2-1/2%s\n", tail);\r
+ if(score > 0 && stm == WHITE || score < 0 && stm == BLACK) printf("1-0%s\n", tail);\r
+ else printf("0-1%s\n", tail);\r
}\r
\r
main()\r
if(kcapt) { // print King capture before claiming\r
GenCapts(k, 0);\r
printf("move %s\n", MoveToText(moveStack[msp-1], 1));\r
- }\r
+ reason = "king capture";\r
+ } else reason = "resign";\r
engineSide = NONE; // so stop playing\r
PrintResult(stm, score);\r
} else {\r
if(!strcmp(command, "memory")) { SetMemorySize(atoi(inBuf+7)); continue; }\r
if(!strcmp(command, "ping")) { printf("pong%s", inBuf+4); continue; }\r
// if(!strcmp(command, "")) { sscanf(inBuf, " %d", &); continue; }\r
- if(!strcmp(command, "new")) { engineSide = BLACK; Init(V_CHESS); stm = Setup2(DEFAULT_FEN); maxDepth = MAXPLY; randomize = OFF; continue; }\r
+ if(!strcmp(command, "new")) {\r
+ engineSide = BLACK; Init(V_CHESS); stm = Setup2(DEFAULT_FEN); 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, "easy")) { ponder = OFF; continue; }\r
if(!strcmp(command, "hard")) { ponder = ON; continue; }\r
if(!strcmp(command, "l")) { pplist(); continue; }\r
// ignored commands:\r
if(!strcmp(command, "xboard")) { continue; }\r
- if(!strcmp(command, "computer")){ continue; }\r
+ if(!strcmp(command, "computer")){ comp = 1; continue; }\r
if(!strcmp(command, "name")) { continue; }\r
if(!strcmp(command, "ics")) { continue; }\r
if(!strcmp(command, "accepted")){ continue; }\r
if(!strcmp(command, "")) { continue; }\r
if(!strcmp(command, "usermove")){\r
int move = ParseMove(inBuf+9);\r
- if(move == INVALID) printf("Illegal move\n");\r
- else {\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
+ } else {\r
stm = MakeMove2(stm, move);\r
ponderMove = INVALID;\r
gameMove[moveNr++] = move; // remember game\r