Remove *.o on "make clean"
[hachu.git] / hachu.c
diff --git a/hachu.c b/hachu.c
index 2401644..11e5710 100644 (file)
--- a/hachu.c
+++ b/hachu.c
@@ -89,6 +89,7 @@
 #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
@@ -127,6 +128,7 @@ char *MoveToText(Move move, int m);     // from WB driver
 void pmap(int *m, int col);\r
 void pboard(int *b);\r
 void pbytes(unsigned char *b);\r
+int myRandom();\r
 \r
 typedef struct {\r
   int lock[5];\r
@@ -153,7 +155,7 @@ typedef struct {
 } 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
@@ -498,7 +500,7 @@ Vector direction[] = { // clockwise!
   { 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
@@ -620,7 +622,7 @@ int rawBoard[BSIZE + 11*BHMAX + 6];
 int attackMaps[200*BSIZE], *attacks = attackMaps;\r
 char distance[2*BSIZE]; // distance table\r
 char promoBoard[BSIZE]; // flags to indicate promotion zones\r
-char rawFire[BSIZE+2*BWMAX]; // flags to indicate squares controlled by Fire Demons\r
+unsigned char rawFire[BSIZE+2*BWMAX]; // flags to indicate squares controlled by Fire Demons\r
 signed char PST[7*BSIZE];\r
 \r
 #define board     (rawBoard + 6*BHMAX + 3)\r
@@ -707,7 +709,6 @@ Lance (signed char *r)
 int\r
 EasyProm (signed char *r)\r
 {\r
-  int i;\r
   if(r[0] == X) return 30 + PROMO*((unsigned int)(r[1] | r[2] | r[3] | r[5] | r[6] | r[7]) <= 1);\r
   if(r[1] == X || r[7] == X) return 30 + PROMO/2;\r
   return 0;\r
@@ -762,7 +763,7 @@ StackMultis (int col)
 void\r
 Compactify (int stm)\r
 { // remove pieces that are permanently gone (captured or promoted) from one side's piece list\r
-  int i, j, k;\r
+  int i, k;\r
   for(i=stm+2; i<=last[stm]; i+=2) { // first pass: unpromoted pieces\r
     if((k = p[i].promo) >= 0 && p[i].pos == ABSENT) { // unpromoted piece no longer there\r
       p[k].promo = -2; // orphan promoted version\r
@@ -814,10 +815,10 @@ AddPiece (int stm, PieceDesc *list)
 }\r
 \r
 void\r
-SetUp(char *array, int var)\r
+SetUp (char *array, int var)\r
 {\r
-  int i, j, n, m, nr, color;\r
-  char c, *q, name[3], prince = 0;\r
+  int i, j, n, m, color;\r
+  char c, name[3], prince = 0;\r
   PieceDesc *p1, *p2;\r
   last[WHITE] = 1; last[BLACK] = 0;\r
   royal[WHITE] = royal[BLACK] = 0;\r
@@ -959,6 +960,11 @@ Init (int var)
     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
@@ -1094,7 +1100,7 @@ char mapStep[] = { 7, 8, 1, -6, -7, -8, -1, 6 };
 char rowMask[] = { 0100, 0140, 0160, 070, 034, 016, 07, 03, 01 };\r
 char rows[9];\r
 \r
-int\r
+void\r
 AreaStep (int from, int x, int flags, int n, int d)\r
 {\r
   int i;\r
@@ -1108,7 +1114,7 @@ AreaStep (int from, int x, int flags, int n, int d)
   }\r
 }\r
 \r
-int\r
+void\r
 AreaMoves (int from, int piece, int range)\r
 {\r
   int i;\r
@@ -1135,6 +1141,17 @@ MarkBurns (int x)
   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
@@ -1182,7 +1199,7 @@ report (int x, int y, int i)
 int\r
 MapOneColor (int start, int last, int *map)\r
 {\r
-  int i, j, k, totMob = 0;\r
+  int i, j, totMob = 0;\r
   for(i=start+2; i<=last; i+=2) {\r
     int mob = 0;\r
     if(p[i].pos == ABSENT) continue;\r
@@ -1309,6 +1326,21 @@ MakeMove(Move m, UndoInfo *u)
   } 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
@@ -1335,6 +1367,7 @@ MakeMove(Move m, UndoInfo *u)
     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
@@ -1431,13 +1464,13 @@ UnMake(UndoInfo *u)
 }\r
        \r
 void\r
-GenCapts(int sqr, int victimValue)\r
+GenCapts (int sqr, int victimValue)\r
 { // generate all moves that capture the piece on the given square\r
-  int i, range, att = attacks[2*sqr + stm];\r
+  int i, att = attacks[2*sqr + stm];\r
 //printf("GenCapts(%c%d,%d) %08x\n",sqr%BW+'a',sqr/BW,victimValue,att);\r
   if(!att) return; // no attackers at all!\r
   for(i=0; i<8; i++) {               // try all rays\r
-    int x, v, jumper, jcapt=0;\r
+    int x, v, jcapt=0;\r
     if(att & attackMask[i]) {        // attacked by move in this direction\r
       v = -kStep[i]; x = sqr;\r
       while( board[x+=v] == EMPTY ); // scan towards source until we encounter a 'stop'\r
@@ -2384,7 +2417,8 @@ MoveToText (MOVE move, int multiLine)
   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
@@ -2395,6 +2429,7 @@ MoveToText (MOVE move, int multiLine)
       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
@@ -2405,7 +2440,7 @@ MoveToText (MOVE move, int multiLine)
 int\r
 ReadSquare (char *p, int *sqr)\r
 {\r
-  int i=0, f, r;\r
+  int f, r;\r
   f = p[0] - 'a';\r
   r = atoi(p + 1) - ONE;\r
   *sqr = r*BW + f;\r
@@ -2425,7 +2460,8 @@ MapFromScratch(attacks);
   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
@@ -2451,6 +2487,11 @@ ParseMove (char *moveText)
       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
@@ -2500,6 +2541,7 @@ Highlight(char *coords)
   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
@@ -2565,7 +2607,7 @@ printf("# limits %d, %d, %d mode = %d\n", tlim1, tlim2, tlim3, abortFlag);
 int\r
 SearchBestMove (MOVE *move, MOVE *ponderMove)\r
 {\r
-  int score, i;\r
+  int score;\r
 printf("# SearchBestMove\n");\r
   startTime = GetTickCount();\r
   nodes = 0;\r
@@ -2644,18 +2686,21 @@ printf("# ponder hit\n");
       }\r
     }\r
 \r
+    int\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
@@ -2827,5 +2872,6 @@ pboard(board);
         if(!strcmp(command, "remove"))  { stm = TakeBack(2); continue; }\r
         printf("Error: unknown command\n");\r
       }\r
+      return 0;\r
     }\r
 \r