#define PROMOTE (1<<2*SQLEN+1) /* promotion bit in move */\r
#define SPECIAL 1400 /* start of special moves */\r
#define BURN (SPECIAL + 96) /* start of burn encodings */\r
+#define CASTLE (SPECIAL + 100) /* castling encodings */\r
#define STEP(X,Y) (BW*(X)+ (Y))\r
#define SORTKEY(X) 0\r
\r
{ 2,-1}\r
};\r
\r
-int epList[96], ep2List[96], toList[96], reverse[96]; // decoding tables for double and triple moves\r
+int epList[104], ep2List[104], toList[104], reverse[104]; // decoding tables for double and triple moves\r
int kingStep[10], knightStep[10]; // raw tables for step vectors (indexed as -1 .. 8)\r
int neighbors[9]; // similar to kingStep, but starts with null-step\r
char fireFlags[10]; // flags for Fire-Demon presence (last two are dummies, which stay 0, for compactify)\r
toList[88+i] = kStep[i]; epList[88+i] = 2*kStep[i];\r
}\r
\r
+ toList[100] = BH - 2; epList[100] = BH - 1; ep2List[100] = BH - 3;\r
+ toList[100+1] = 2; epList[100+1] = 0; ep2List[100+1] = 3;\r
+ toList[100+2] = bsize - BH - 2; epList[100+2] = bsize - BH - 1; ep2List[100+2] = bsize - BH - 3;\r
+ toList[100+3] = bsize - BW + 2; epList[100+3] = bsize - BW; ep2List[100+3] = bsize - BW + 3;\r
+\r
// fill distance table\r
for(i=0; i<2*BSIZE; i++) {\r
distance[i] = 0;\r
for(r=b; r<=t-2; r++) rows[r] |= rows[r+1] | rows[r+2]; // smear vertically\r
}\r
\r
+void\r
+GenCastlings ()\r
+{ // castings for Lion Chess. Assumes board width = 8 and Kings on e-file, and K/R value = 280/300!\r
+ int f = BH>>1, t = CASTLE;\r
+ if(stm != WHITE) f += bsize - BW, t += 2;\r
+ if(p[board[f]].value = 280) {\r
+ if(p[board[f-4]].value == 300 && board[f-3] == EMPTY && board[f-2] == EMPTY && board[f-1] == EMPTY) moveStack[msp++] = f<<SQLEN | t+1;\r
+ if(p[board[f+3]].value == 300 && board[f+1] == EMPTY && board[f+2] == EMPTY) moveStack[msp++] = f<<SQLEN | t;\r
+ }\r
+}\r
+\r
int\r
GenNonCapts (int promoSuppress)\r
{\r
} else u->new = u->piece;\r
\r
if(u->to >= SPECIAL) { // two-step Lion move\r
+ if(u->to >= CASTLE) { // move Rook, faking it was an e.p. victim so that UnMake works automatically\r
+ u->epSquare = epList[u->to - SPECIAL];\r
+ u->ep2Square = ep2List[u->to - SPECIAL];\r
+ u->epVictim[0] = board[u->epSquare]; // kludgy: fake that King e.p. captured the Rook!\r
+ u->epVictim[1] = board[u->ep2Square]; // should be EMPTY (but you never know, so save as well).\r
+ board[u->ep2Square] = u->epVictim[0]; // but put Rook back\r
+ board[u->epSquare] = EMPTY;\r
+ p[u->epVictim[0]].pos = u->ep2Square;\r
+ p[u->epVictim[1]].pos = ABSENT;\r
+ u->to = toList[u->to - SPECIAL];\r
+ hashKeyL ^= p[u->epVictim[0]].pieceKey * squareKey[u->epSquare];\r
+ hashKeyH ^= p[u->epVictim[0]].pieceKey * squareKey[u->epSquare+BH];\r
+ hashKeyL ^= p[u->epVictim[0]].pieceKey * squareKey[u->ep2Square];\r
+ hashKeyH ^= p[u->epVictim[0]].pieceKey * squareKey[u->ep2Square+BH];\r
+ } else {\r
// take care of first e.p. victim\r
u->epSquare = u->from + epList[u->to - SPECIAL]; // decode\r
u->epVictim[0] = board[u->epSquare]; // remember for takeback\r
hashKeyH ^= p[u->epVictim[1]].pieceKey * squareKey[u->ep2Square+BH];\r
if(p[u->piece].value != LVAL && p[u->epVictim[0]].value == LVAL) deferred |= PROMOTE; // flag non-Lion x Lion\r
cnt50 = 0; // double capture irreversible\r
+ }\r
}\r
\r
if(u->fireMask & fireBoard[u->to]) { // we moved next to enemy Fire Demon (must be done after SPECIAL, to decode to-sqr)\r
char *promoChar = "";\r
if(f == t) { sprintf(buf, "@@@@"); return buf; } // null-move notation in WB protocol\r
buf[0] = '\0';\r
- if(t >= SPECIAL) { // kludgy! Print as side effect non-standard WB command to remove victims from double-capture (breaks hint command!)\r
+ if(t >= SPECIAL) {\r
+ if(t < CASTLE) { // castling is printed as a single move, implying its side effects\r
int e = f + epList[t - SPECIAL];\r
// printf("take %c%d\n", e%BW+'a', e/BW+ONE);\r
sprintf(buf, "%c%d%c%d,", f%BW+'a', f/BW+ONE, e%BW+'a', e/BW+ONE); f = e;\r
sprintf(buf+strlen(buf), "%c%d%c%d,", f%BW+'a', f/BW+ONE, e%BW+'a', e/BW+ONE); f = e;\r
if(multiLine) printf("move %s\n", buf), buf[0] = '\0';\r
}\r
+ }\r
t = g + toList[t - SPECIAL];\r
}\r
if(move & PROMOTE) promoChar = currentVariant == V_MAKRUK ? "m" : repDraws ? "q" : "+";\r
Search(-INF-1, INF+1, 0, QSdepth+1, 0, sup1 & ~PROMOTE, sup2, INF);\r
postThinking++;\r
\r
- listStart = retFirst; listEnd = msp = retMSP;\r
+ listStart = retFirst; msp = retMSP;\r
+ if(currentVariant == V_LION) GenCastlings(); listEnd = msp;\r
}\r
\r
MOVE\r
if(t == f + BW - 1) t2 = SPECIAL + 48; else\r
if(t == f - BW + 1) t2 = SPECIAL + 20; else\r
if(t == f - BW - 1) t2 = SPECIAL + 52; // fake double-move\r
+ } else if(currentVariant == V_LION && board[f] != EMPTY && p[board[f]].value == 280 && (t-f == 2 || f-t == 2)) { // castling\r
+ if(t == f+2 && f < BW) t2 = CASTLE; else\r
+ if(t == f-2 && f < BW) t2 = CASTLE + 1; else\r
+ if(t == f+2 && f > BW) t2 = CASTLE + 2; else\r
+ if(t == f-2 && f > BW) t2 = CASTLE + 3;\r
}\r
ret = f<<SQLEN | t2;\r
if(*moveText != '\n' && *moveText != '=') ret |= PROMOTE;\r
for(i=listStart; i<listEnd; i++) {\r
if(sqr == (moveStack[i]>>SQLEN & SQUARE)) {\r
int t = moveStack[i] & SQUARE;\r
+ if(t >= CASTLE) t = toList[t - SPECIAL]; else // decode castling\r
if(t >= SPECIAL) {\r
int e = sqr + epList[t - SPECIAL]; // decode\r
b[e] = 'C';\r