#include <ctype.h>
#include <fcntl.h>
+#define DUMP_FEN 0
+#define DUMP_ENC 0
+
int cto_fd, ctg_fd, ctb_fd;
unsigned int tbl2[] = {
}
}
+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;
}
}
+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;
}
}
}
-
- // 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) {
}
// 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;
if (ep_any)
position[0] |= 0x20;
-#if 1
- // dump
+#if DUMP_ENC
{
int i;
for (i = 0; i < pos_len; ++i) {
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,
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,
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,
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,
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,
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,
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)
}
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)
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, "-");
// 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, "-");
}
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';
#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];
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) {
}
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]);
}
}
{
// 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
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);
}