// promotions by pieces with Lion power stepping in & out the zone in same turn\r
// promotion on capture\r
\r
-#define VERSION "0.19"\r
+#define VERSION "0.20"\r
\r
//define PATH level==0 || path[0] == 0x590cb && (level==1 || path[1] == 0x4c0c9 && (level == 2 || path[2] == 0x8598ca && (level == 3 /*|| path[3] == 0x3e865 && (level == 4 || path[4] == 0x4b865 && (level == 5))*/)))\r
#define PATH 0\r
#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
} PieceDesc;\r
\r
typedef struct {\r
- int from, to, piece, victim, new, booty, epSquare, epVictim[8], ep2Square, revMoveCount;\r
+ int from, to, piece, victim, new, booty, epSquare, epVictim[9], ep2Square, revMoveCount;\r
int savKeyL, savKeyH, gain, loss, filling, saveDelta;\r
char fireMask;\r
} UndoInfo;\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
{\r
if(board[y] != EMPTY) return 1; // edge, capture or own piece\r
//if(flag) printf("# add %c%d%c%d, pf=%d\n", x%BW+'a',x/BW,y%BW+'a',y/BW, promoFlags);\r
- if( (promoBoard[x] | promoBoard[y]) & promoFlags &&\r
- (!entryProm || promoBoard[y] & ~promoBoard[x] & CAN_PROMOTE )){ // piece can promote with this move\r
+ if( (entryProm ? promoBoard[y] & ~promoBoard[x] & CAN_PROMOTE\r
+ : promoBoard[y] | promoBoard[x] ) & promoFlags ){ // piece can promote with this move\r
moveStack[msp++] = moveStack[nonCapts]; // create space for promotion\r
moveStack[nonCapts++] = x<<SQLEN | y | PROMOTE; // push promotion\r
if((promoFlags & promoBoard[y] & (CANT_DEFER | DONT_DEFER | LAST_RANK)) == 0) { // deferral could be a better alternative\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
if(!*fen) break;\r
fen++;\r
}\r
+ *p = '\0';\r
printf("# converted FEN '%s'\n", fenArray);\r
return fenArray;\r
}\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
\r
main()\r
{\r
- int engineSide=NONE; // side played by engine\r
+ int engineSide=NONE; // side played by engine\r
MOVE move;\r
int i, score, curVarNr;\r
\r
- Init(V_CHU); // Chu\r
+ setvbuf(stdin, NULL, _IOLBF, 1024); // buffering more than one line flaws test for pending input!\r
+\r
+ Init(V_CHU); // Chu\r
seed = startTime = GetTickCount(); moveNr = 0; // initialize random\r
\r
while(1) { // infinite loop\r
\r
- fflush(stdout); // make sure everything is printed before we do something that might take time\r
+ fflush(stdout); // make sure everything is printed before we do something that might take time\r
*inBuf = 0; if(moveNr >= 20) randomize = OFF;\r
//if(moveNr >20) printf("resign\n");\r
\r