booklook improvements -- too many to mention.
authorSteinar H. Gunderson <sesse@debian.org>
Thu, 19 Jul 2007 14:55:11 +0000 (16:55 +0200)
committerSteinar H. Gunderson <sesse@debian.org>
Thu, 19 Jul 2007 14:55:11 +0000 (16:55 +0200)
booklook.c

index c9eea59..1d1c713 100644 (file)
@@ -4,6 +4,9 @@
 #include <ctype.h>
 #include <fcntl.h>
 
+#define DUMP_FEN 0
+#define DUMP_ENC 0
+
 int cto_fd, ctg_fd, ctb_fd;
 
 unsigned int tbl2[] = {
@@ -161,6 +164,45 @@ void invert_board(char *board)
        }
 }
 
+int needs_flipping(char *board, char *castling_rights)
+{
+       int y, x;
+
+       // never flip if either side can castle
+       if (strcmp(castling_rights, "-") != 0)
+               return 0;
+
+       for (y = 0; y < 8; ++y) {
+               for (x = 0; x < 4; ++x) {
+                       if (board[y * 8 + x] == 'K')
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+// horizontal flip
+void flip_board(char *board, char *eps)
+{
+       int y, x;
+
+       // flip the board
+       for (y = 0; y < 8; ++y) {
+               for (x = 0; x < 4; ++x) {
+                       char tmp = board[y * 8 + x];
+                       board[y * 8 + (x)] = board[y * 8 + (7-x)];
+                       board[y * 8 + (7-x)] = tmp;
+               }
+       }
+
+       // flip the en passant square
+       if (strcmp(eps, "-") != 0) {
+               int epsc = eps[0] - 'a';
+               eps[0] = 'a' + (7 - epsc);
+       }
+}
+
 unsigned char position[32];
 int pos_len;
 int bits_left;
@@ -177,6 +219,43 @@ void put_bit(int x)
        }
 }
 
+void dump_fen(char *board, int invert, int flip, char *castling_rights, char *ep_square)
+{
+       int y, x;
+       for (y = 0; y < 8; ++y) {
+               int space = 0;
+               for (x = 0; x < 8; ++x) {
+                       int xx = (flip) ? (7-x) : x;
+
+                       if (board[y * 8 + xx] == ' ') {
+                               ++space;
+                       } else {
+                               if (space != 0)
+                                       putchar('0' + space);
+                               putchar(board[y * 8 + xx]);
+                               space = 0;
+                       }
+               }
+               if (space != 0)
+                       putchar('0' + space);
+               if (y != 7)
+                       putchar('/');
+       }
+       putchar(' ');
+
+       if (invert)
+               putchar('b');
+       else
+               putchar('w');
+
+       printf(" %s ", castling_rights);
+       if (flip && strcmp(ep_square, "-") != 0) {
+               printf("%c%c 0 0\n", 'a' + (7 - (ep_square[0] - 'a')), ep_square[1]);
+       } else {
+               printf("%s 0 0\n", ep_square);
+       }
+}
+
 void encode_position(char *board, int invert, char *castling_rights, char *ep_column)
 {
        int x, y;
@@ -283,36 +362,52 @@ void encode_position(char *board, int invert, char *castling_rights, char *ep_co
                        }
                }
        }
-
-       // en passant
+               
        if (strcmp(ep_column, "-") != 0) {
                int epcn = ep_column[0] - 'a';
 
-               // only encode en passant if a capture is actually possible
                if ((epcn > 0 && board[3*8 + epcn - 1] == 'P') ||
                    (epcn < 7 && board[3*8 + epcn + 1] == 'P')) {
-                       ep_any = 1;
-
-                       put_bit(epcn & 0x80);
-                       put_bit(epcn & 0x40);
-                       put_bit(epcn & 0x20);
-                       put_bit(epcn & 0x10);
-                       put_bit(epcn & 0x08);
-                       put_bit(epcn & 0x04);
-                       put_bit(epcn & 0x02);
-                       put_bit(epcn & 0x01);
+                       ep_any = 1;
                }
        }
-
+       
        // really odd padding
-       if (bits_left > 4) {
-               int i, nb = bits_left - 4;
+       {
+               int nb = 0, i;
+
+               // find the right number of bits
+               int right = (ep_any) ? 3 : 8;
+
+               // castling needs four more
+               if (strcmp(castling_rights, "-") != 0) {
+                       right = right + 4;
+                       if (right > 8)
+                               right %= 8;
+               }
+
+               if (bits_left > right)
+                       nb = bits_left - right;
+               else if (bits_left < right)
+                       nb = bits_left + 8 - right;
+
+               if (bits_left == 8 && strcmp(castling_rights, "-") == 0 && !ep_any)
+                       nb = 8;
+
                for (i = 0; i < nb; ++i) {
-                       //printf("spare bit\n");
                        put_bit(0);
                }
        }
        
+       // en passant
+       if (ep_any) {
+               int epcn = ep_column[0] - 'a';
+
+               put_bit(epcn & 0x04);
+               put_bit(epcn & 0x02);
+               put_bit(epcn & 0x01);
+       }
+       
        // castling rights
        if (strcmp(castling_rights, "-") != 0) {
                if (invert) {
@@ -329,13 +424,17 @@ void encode_position(char *board, int invert, char *castling_rights, char *ep_co
        }
 
        // padding stuff
-#if 1
-       if (bits_left != 8) {
+       if (bits_left == 8) {
+               //++pos_len;
+       } else {
+#if 0
+               ++pos_len;
+#else
                int i, nd = 8 - bits_left;
                for (i = 0; i < nd; ++i)
                        put_bit(0);
-       }
 #endif
+       }
                
        // and the header byte
        position[0] = pos_len;
@@ -345,8 +444,7 @@ void encode_position(char *board, int invert, char *castling_rights, char *ep_co
        if (ep_any)
                position[0] |= 0x20;
 
-#if 0
-       // dump
+#if DUMP_ENC
        {
                int i;
                for (i = 0; i < pos_len; ++i) {
@@ -428,9 +526,11 @@ struct moveenc {
 struct moveenc movetable[] = {
        0x00, 'P', 5,  1,  1,
        0x01, 'N', 2, -1, -2,
+       0x03, 'Q', 2,  0,  2,
        0x04, 'P', 2,  1,  0,
        0x05, 'Q', 1,  1,  0,
        0x06, 'P', 4,  1, -1,
+       0x08, 'Q', 2,  0,  4, 
        0x09, 'B', 2,  6,  6,
        0x0a, 'K', 1, -1,  0,
        0x0c, 'P', 1,  1, -1,
@@ -442,10 +542,12 @@ struct moveenc movetable[] = {
        0x14, 'P', 8,  1,  1,
        0x15, 'B', 1,  5,  5,
        0x18, 'P', 7,  1,  0,
+       0x1a, 'Q', 2,  6,  0,
        0x1b, 'B', 1,  1, -1,
        0x1d, 'B', 2,  7,  7,
        0x21, 'R', 2,  0,  7,
        0x22, 'B', 2,  2, -2,
+       0x23, 'Q', 2,  6,  6,
        0x24, 'P', 8,  1, -1,
        0x26, 'B', 1,  7, -7,
        0x27, 'P', 3,  1, -1,
@@ -461,15 +563,19 @@ struct moveenc movetable[] = {
        0x34, 'N', 1,  2,  1,
        0x36, 'N', 1,  1,  2,
        0x37, 'Q', 1,  4,  0,
+       0x38, 'Q', 2,  4, -4,
        0x39, 'Q', 1,  0,  5,
        0x3a, 'B', 1,  6,  6,
+       0x3b, 'Q', 2,  5, -5,
        0x3c, 'B', 1,  5, -5,
+       0x41, 'Q', 2,  5,  5,
        0x42, 'Q', 1,  7, -7,
        0x44, 'K', 1, -1,  1,
        0x45, 'Q', 1,  3,  3,
        0x4a, 'P', 8,  2,  0,
        0x4b, 'Q', 1,  5, -5,
        0x4c, 'N', 2,  2,  1,
+       0x4d, 'Q', 2,  1,  0,
        0x50, 'R', 1,  6,  0,
        0x52, 'R', 1,  0,  6,
        0x54, 'B', 2,  1, -1,
@@ -478,12 +584,14 @@ struct moveenc movetable[] = {
        0x5f, 'P', 5,  2,  0,
        0x61, 'Q', 1,  6,  6,
        0x62, 'P', 2,  2,  0,
+       0x63, 'Q', 2,  7, -7,
        0x66, 'B', 1,  3, -3,
        0x67, 'K', 1,  1,  1,
        0x69, 'R', 2,  7,  0,
        0x6a, 'B', 1,  4,  4,
        0x6b, 'K', 1,  0,  2,   /* short castling */
        0x6e, 'R', 1,  0,  5,
+       0x6f, 'Q', 2,  7,  7,
        0x72, 'B', 2,  7, -7,
        0x74, 'Q', 1,  0,  2,
        0x79, 'B', 2,  6, -6,
@@ -502,7 +610,9 @@ struct moveenc movetable[] = {
        0x8a, 'N', 1, -2,  1,
        0x8b, 'P', 1,  1,  1,
        0x8c, 'K', 1, -1, -1,
+       0x8e, 'Q', 2,  2, -2,
        0x8f, 'Q', 1,  0,  7,
+       0x92, 'Q', 2,  1,  1,
        0x94, 'Q', 1,  3,  0,
        0x96, 'P', 2,  1,  1,
        0x97, 'K', 1,  0, -1,
@@ -512,25 +622,33 @@ struct moveenc movetable[] = {
        0x9b, 'P', 3,  2,  0,
        0x9d, 'Q', 1,  2,  0,
        0x9f, 'B', 2,  4, -4,
+       0xa0, 'Q', 2,  3,  0,
        0xa2, 'Q', 1,  2,  2,
        0xa3, 'P', 8,  1,  0,
        0xa5, 'R', 2,  5,  0,
        0xa9, 'R', 2,  0,  2,
+       0xab, 'Q', 2,  6, -6,
        0xad, 'R', 2,  0,  4,
+       0xae, 'Q', 2,  3,  3,
+       0xb0, 'Q', 2,  4,  0,
        0xb1, 'P', 6,  2,  0,
        0xb2, 'B', 1,  6, -6,
        0xb5, 'R', 2,  0,  5,
        0xb7, 'Q', 1,  5,  0,
        0xb9, 'B', 2,  3,  3,
        0xbb, 'P', 5,  1,  0,
+       0xbc, 'Q', 2,  0,  5,
+       0xbd, 'Q', 2,  2,  0,
        0xbe, 'K', 1,  0,  1,
        0xc1, 'B', 1,  2,  2,
        0xc2, 'B', 2,  2,  2,
        0xc3, 'B', 1,  2, -2,
        0xc4, 'R', 2,  0,  1,
        0xc5, 'R', 2,  4,  0,
+       0xc6, 'Q', 2,  5,  0,
        0xc7, 'P', 7,  1, -1,
        0xc8, 'P', 7,  2,  0,
+       0xc9, 'Q', 2,  7,  0,
        0xca, 'B', 2,  3, -3,
        0xcb, 'P', 6,  1,  0,
        0xcc, 'B', 2,  5, -5,
@@ -557,14 +675,21 @@ struct moveenc movetable[] = {
        0xeb, 'P', 4,  1,  1,
        0xec, 'P', 1,  1,  0,
        0xed, 'Q', 1,  7,  7,
+       0xee, 'Q', 2,  1, -1,
        0xef, 'R', 1,  0,  4,
+       0xf0, 'Q', 2,  0,  7,
        0xf1, 'Q', 1,  1,  1,
        0xf3, 'N', 2,  2, -1,
        0xf4, 'R', 2,  2,  0,
        0xf5, 'B', 2,  1,  1,
        0xf6, 'K', 1,  0, -2,   /* long castling */
        0xf7, 'N', 1,  1, -2,
-       0xfd, 'Q', 1,  7,  0
+       0xf8, 'Q', 2,  0,  1,
+       0xf9, 'Q', 2,  6,  0,
+       0xfa, 'Q', 2,  0,  3,
+       0xfb, 'Q', 2,  2,  2,
+       0xfd, 'Q', 1,  7,  0,
+       0xfe, 'Q', 2,  3, -3
 };
 
 int find_piece(char *board, char piece, int num)
@@ -580,6 +705,7 @@ int find_piece(char *board, char piece, int num)
        }
 
        fprintf(stderr, "Couldn't find piece '%c' number %u\n", piece, num);
+       exit(1);
 }
 
 void execute_move(char *board, char *castling_rights, int inverted, char *ep_square, int from_square, int to_square)
@@ -601,19 +727,33 @@ void execute_move(char *board, char *castling_rights, int inverted, char *ep_squ
                        black_ks = black_qs = 0;
                else
                        white_ks = white_qs = 0;
-       } else if (board[from_square] == 'R') {
+       }
+       if (board[from_square] == 'R') {
                if (inverted) {
-                       if (from_square == 0) // a1
+                       if (from_square == 56) // h1
                                black_qs = 0;
-                       else if (from_square == 7 * 8 + 0) // a8
+                       else if (from_square == 63) // h8
                                black_ks = 0;
                } else {
-                       if (from_square == 0) // a1
+                       if (from_square == 56) // a1
                                white_qs = 0;
-                       else if (from_square == 7 * 8 + 0) // a8
+                       else if (from_square == 63) // a8
                                white_ks = 0;
                }
        }
+       if (board[to_square] == 'r') {
+               if (inverted) {
+                       if (to_square == 0) // h1
+                               white_qs = 0;
+                       else if (to_square == 7) // h8
+                               white_ks = 0;
+               } else {
+                       if (to_square == 0) // a1
+                               black_qs = 0;
+                       else if (to_square == 7) // a8
+                               black_ks = 0;
+               }
+       }
 
        if ((black_ks | black_qs | white_ks | white_qs) == 0) {
                strcpy(castling_rights, "-");
@@ -632,7 +772,7 @@ void execute_move(char *board, char *castling_rights, int inverted, char *ep_squ
 
        // now the ep square
        if (board[from_square] == 'P' && to_square - from_square == -16) {
-               sprintf(ep_square, "%c%u", "abcdefgh"[from_square % 8], from_square / 8 + 2);
+               sprintf(ep_square, "%c%u", "abcdefgh"[from_square % 8], from_square / 8);
        } else {
                strcpy(ep_square, "-");
        }
@@ -647,6 +787,10 @@ void execute_move(char *board, char *castling_rights, int inverted, char *ep_squ
        board[to_square] = board[from_square];
        board[from_square] = ' ';
 
+       // promotion
+       if (board[to_square] == 'P' && to_square < 8)
+               board[to_square] = 'Q';
+
        if (board[to_square] == 'K' && to_square - from_square == 2) {
                // short castling
                board[to_square - 1] = 'R';
@@ -673,7 +817,7 @@ void execute_move(char *board, char *castling_rights, int inverted, char *ep_squ
 #endif
 }
 
-void dump_move(char *board, char *castling_rights, char *ep_col, int invert, char move, char annotation)
+void dump_move(char *board, char *castling_rights, char *ep_col, int invert, int flip, char move, char annotation)
 {
        int i;
        char newboard[64], nkr[5], neps[3];
@@ -693,16 +837,60 @@ void dump_move(char *board, char *castling_rights, char *ep_col, int invert, cha
                to_row = (from_row + 8 + movetable[i].forward) % 8;
                to_col = (from_col + 8 + movetable[i].right) % 8;
                to_square = to_row * 8 + to_col;
+               
+               // do the move, and look up the new position
+               memcpy(newboard, board, 64);
+               strcpy(nkr, castling_rights);
+               execute_move(newboard, nkr, invert, neps, from_square, to_square);
+               invert_board(newboard);
+               
+               if (needs_flipping(newboard, nkr)) {
+                       flip_board(newboard, neps);
+                       flip = !flip;
+               }
+               
+               encode_position(newboard, !invert, nkr, neps);
+               ret = lookup_position(position, pos_len, result);
+               if (!ret) {
+#if DUMP_FEN
+                       if (!invert) 
+                               invert_board(newboard);
+
+                       dump_fen(newboard, !invert, flip, nkr, neps);
+#endif
+                       fprintf(stderr, "Destination move not found in book.\n");
+                       exit(1);
+               }
+
+#if DUMP_FEN
+               // very useful for regression testing (some shell and
+               // you can walk the entire book quite easily)
+               if (!invert) 
+                       invert_board(newboard);
+               dump_fen(newboard, !invert, flip, nkr, neps);
+               return;
+#endif
 
                // output the move
-               if (invert)
-                       printf("%c%u%c%u,",
-                               "abcdefgh"[from_square % 8], (7 - from_square / 8) + 1,
-                               "abcdefgh"[to_square % 8], (7 - to_square / 8) + 1);
-               else
+               {
+                       int fromcol = from_square % 8;
+                       int fromrow = from_square / 8;
+                       int tocol = to_square % 8;
+                       int torow = to_square / 8;
+
+                       if (invert) {
+                               fromrow = 7 - fromrow;
+                               torow = 7 - torow;
+                       }
+                       if (flip) {
+                               fromcol = 7 - fromcol;
+                               tocol = 7 - tocol;
+                       }
+
                        printf("%c%u%c%u,",
-                               "abcdefgh"[from_square % 8], from_square / 8 + 1,
-                               "abcdefgh"[to_square % 8], to_square / 8 + 1);
+                               "abcdefgh"[fromcol], fromrow + 1,
+                               "abcdefgh"[tocol], torow + 1);
+               }
 
                // annotation
                switch (annotation) {
@@ -737,36 +925,26 @@ void dump_move(char *board, char *castling_rights, char *ep_col, int invert, cha
                }
                printf(",");
 
-               // do the move, and look up the new position
-               memcpy(newboard, board, 64);
-               strcpy(nkr, castling_rights);
-               execute_move(newboard, nkr, invert, neps, from_square, to_square);
-               invert_board(newboard);
-       
-               encode_position(newboard, !invert, nkr, neps);
-               ret = lookup_position(position, pos_len, result);
-               if (!ret) {
-                       fprintf(stderr, "Destination move not found in book.\n");
-                       exit(1);
-               }
-
                output_stats(result, invert);
                return;
        }
 
        fprintf(stderr, "ERROR: Unknown move 0x%02x\n", move);
+       exit(1);
 }
 
-void dump_info(char *board, char *castling_rights, char *ep_col, int invert, char *result)
+void dump_info(char *board, char *castling_rights, char *ep_col, int invert, int flip, char *result)
 {
        int book_moves = result[0] >> 1;
        int i;
-               
+       
+#if !DUMP_FEN
        printf(",,");   
        output_stats(result, !invert);
+#endif
 
        for (i = 0; i < book_moves; ++i) {
-               dump_move(board, castling_rights, ep_col, invert, result[i * 2 + 1], result[i * 2 + 2]);
+               dump_move(board, castling_rights, ep_col, invert, flip, result[i * 2 + 1], result[i * 2 + 2]);
        }
 }
 
@@ -774,19 +952,26 @@ int main(int argc, char **argv)
 {
        // encode the position
        char board[64], result[256];
-       int invert = 0;
+       int invert = 0, flip;
        int ret;
        
        ctg_fd = open("RybkaII.ctg", O_RDONLY);
        cto_fd = open("RybkaII.cto", O_RDONLY);
        ctb_fd = open("RybkaII.ctb", O_RDONLY);
        decode_fen_board(argv[1], board);
-
+       
        // always from white's position
        if (argv[2][0] == 'b') {
                invert = 1;
                invert_board(board);
        }
+       
+       // and the white king is always in the right half
+       flip = needs_flipping(board, argv[3]);
+       if (flip) {
+               flip_board(board, argv[4]);
+       }
+
 
 #if 0
        // dump the board
@@ -804,11 +989,11 @@ int main(int argc, char **argv)
        encode_position(board, invert, argv[3], argv[4]);
        ret = lookup_position(position, pos_len, result);
        if (!ret) {
-               printf("Not found in book.\n");
+               fprintf(stderr, "Not found in book.\n");
                exit(1);
        }
 
-       dump_info(board, argv[3], argv[4], invert, result);
+       dump_info(board, argv[3], argv[4], invert, flip, result);
        exit(0);
 }