From f145b782dfbc89176e8e367bbd3351eef6a91786 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 18 Jul 2007 17:52:45 +0200 Subject: [PATCH] Add book lookups. --- booklook.c | 810 ++++++++++++++++++++++++++++++++++++++++++++++++++ remoteglot.pl | 65 +++- 2 files changed, 870 insertions(+), 5 deletions(-) create mode 100644 booklook.c diff --git a/booklook.c b/booklook.c new file mode 100644 index 0000000..c4705b7 --- /dev/null +++ b/booklook.c @@ -0,0 +1,810 @@ +#include +#include +#include +#include +#include + +int cto_fd, ctg_fd, ctb_fd; + +unsigned int tbl2[] = { + 0x3100d2bf, 0x3118e3de, 0x34ab1372, 0x2807a847, + 0x1633f566, 0x2143b359, 0x26d56488, 0x3b9e6f59, + 0x37755656, 0x3089ca7b, 0x18e92d85, 0x0cd0e9d8, + 0x1a9e3b54, 0x3eaa902f, 0x0d9bfaae, 0x2f32b45b, + 0x31ed6102, 0x3d3c8398, 0x146660e3, 0x0f8d4b76, + 0x02c77a5f, 0x146c8799, 0x1c47f51f, 0x249f8f36, + 0x24772043, 0x1fbc1e4d, 0x1e86b3fa, 0x37df36a6, + 0x16ed30e4, 0x02c3148e, 0x216e5929, 0x0636b34e, + 0x317f9f56, 0x15f09d70, 0x131026fb, 0x38c784b1, + 0x29ac3305, 0x2b485dc5, 0x3c049ddc, 0x35a9fbcd, + 0x31d5373b, 0x2b246799, 0x0a2923d3, 0x08a96e9d, + 0x30031a9f, 0x08f525b5, 0x33611c06, 0x2409db98, + 0x0ca4feb2, 0x1000b71e, 0x30566e32, 0x39447d31, + 0x194e3752, 0x08233a95, 0x0f38fe36, 0x29c7cd57, + 0x0f7b3a39, 0x328e8a16, 0x1e7d1388, 0x0fba78f5, + 0x274c7e7c, 0x1e8be65c, 0x2fa0b0bb, 0x1eb6c371 +}; + +signed char data[] = { + 0x36, 0xb6, 0x0f, 0x79, 0x61, 0x1f, 0x50, 0xde, 0x61, 0xb9, 0x52, 0x24, 0xb3, 0xac, 0x6e, 0x5e, 0x0a, 0x69, 0xbd, 0x61, 0x61, 0xc5 +}; + +void output_stats(char *result, int invert) +{ + unsigned char *ptr = result; + ptr += *ptr; + ptr += 3; + + // wins-draw-loss + if (invert) { + printf("%u,", (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]); + printf("%u,", (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]); + printf("%u,", (ptr[3] << 16) | (ptr[4] << 8) | ptr[5]); + } else { + printf("%u,", (ptr[3] << 16) | (ptr[4] << 8) | ptr[5]); + printf("%u,", (ptr[6] << 16) | (ptr[7] << 8) | ptr[8]); + printf("%u,", (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]); + } + + ptr += 9; + ptr += 4; + ptr += 7; + + // rating + { + int rat2_sum, rat2_div; + rat2_div = (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]; + rat2_sum = (ptr[3] << 24) | (ptr[4] << 16) | (ptr[5] << 8) | ptr[6]; + + if (rat2_div == 0) { + printf(",0"); + } else { + printf("%u,%u", rat2_sum / rat2_div, rat2_div); + } + } + + printf("\n"); +} + +unsigned int gen_hash(signed char *ptr, unsigned len) +{ + signed hash = 0; + short tmp = 0; + int i; + + for (i = 0; i < len; ++i) { + signed char ch = *ptr++; + tmp += ((0x0f - (ch & 0x0f)) << 2) + 1; + hash += tbl2[tmp & 0x3f]; + tmp += ((0xf0 - (ch & 0xf0)) >> 2) + 1; + hash += tbl2[tmp & 0x3f]; + } + return hash; +} + +void decode_fen_board(char *str, char *board) +{ + while (*str) { + switch (*str) { + case 'r': + case 'n': + case 'b': + case 'q': + case 'k': + case 'p': + case 'R': + case 'N': + case 'B': + case 'Q': + case 'K': + case 'P': + *board++ = *str; + break; + case '8': + *board++ = ' '; + // fall through + case '7': + *board++ = ' '; + // fall through + case '6': + *board++ = ' '; + // fall through + case '5': + *board++ = ' '; + // fall through + case '4': + *board++ = ' '; + // fall through + case '3': + *board++ = ' '; + // fall through + case '2': + *board++ = ' '; + // fall through + case '1': + *board++ = ' '; + break; + case '/': + // ignore + break; + default: + fprintf(stderr, "Unknown FEN board character '%c'\n", *str); + exit(1); + } + + ++str; + } +} + +void invert_board(char *board) +{ + int y, x, i; + + // flip the board + for (y = 0; y < 4; ++y) { + for (x = 0; x < 8; ++x) { + char tmp = board[y * 8 + (x)]; + board[y * 8 + (x)] = board[(7-y) * 8 + (x)]; + board[(7-y) * 8 + (x)] = tmp; + } + } + + // invert the colors + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + if (board[y * 8 + x] == toupper(board[y * 8 + x])) { + board[y * 8 + x] = tolower(board[y * 8 + x]); + } else { + board[y * 8 + x] = toupper(board[y * 8 + x]); + } + } + } +} + +unsigned char position[32]; +int pos_len; +int bits_left; + +void put_bit(int x) +{ + position[pos_len] <<= 1; + if (x) + position[pos_len] |= 1; + + if (--bits_left == 0) { + ++pos_len; + bits_left = 8; + } +} + +void encode_position(char *board, int invert, char *castling_rights, char *ep_column) +{ + int x, y; + int ep_any = 0; + + // clear out + memset(position, 0, 32); + + // leave some room for the header byte, which will be filled last + pos_len = 1; + bits_left = 8; + + // slightly unusual ordering + for (x = 0; x < 8; ++x) { + for (y = 0; y < 8; ++y) { + switch (board[(7-y) * 8 + x]) { + case ' ': + put_bit(0); + break; + case 'p': + put_bit(1); + put_bit(1); + put_bit(1); + break; + case 'P': + put_bit(1); + put_bit(1); + put_bit(0); + break; + case 'r': + put_bit(1); + put_bit(0); + put_bit(1); + put_bit(1); + put_bit(1); + break; + case 'R': + put_bit(1); + put_bit(0); + put_bit(1); + put_bit(1); + put_bit(0); + break; + case 'b': + put_bit(1); + put_bit(0); + put_bit(1); + put_bit(0); + put_bit(1); + break; + case 'B': + put_bit(1); + put_bit(0); + put_bit(1); + put_bit(0); + put_bit(0); + break; + case 'n': + put_bit(1); + put_bit(0); + put_bit(0); + put_bit(1); + put_bit(1); + break; + case 'N': + put_bit(1); + put_bit(0); + put_bit(0); + put_bit(1); + put_bit(0); + break; + case 'q': + put_bit(1); + put_bit(0); + put_bit(0); + put_bit(0); + put_bit(1); + put_bit(1); + break; + case 'Q': + put_bit(1); + put_bit(0); + put_bit(0); + put_bit(0); + put_bit(1); + put_bit(0); + break; + case 'k': + put_bit(1); + put_bit(0); + put_bit(0); + put_bit(0); + put_bit(0); + put_bit(1); + break; + case 'K': + put_bit(1); + put_bit(0); + put_bit(0); + put_bit(0); + put_bit(0); + put_bit(0); + break; + } + } + } + + // 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); + } + } + + // really odd padding + if (bits_left > 4) { + int i, nb = bits_left - 4; + for (i = 0; i < nb; ++i) { + //printf("spare bit\n"); + put_bit(0); + } + } + + // castling rights + if (strcmp(castling_rights, "-") != 0) { + if (invert) { + put_bit(strchr(castling_rights, 'K') != NULL); + put_bit(strchr(castling_rights, 'Q') != NULL); + put_bit(strchr(castling_rights, 'k') != NULL); + put_bit(strchr(castling_rights, 'q') != NULL); + } else { + put_bit(strchr(castling_rights, 'k') != NULL); + put_bit(strchr(castling_rights, 'q') != NULL); + put_bit(strchr(castling_rights, 'K') != NULL); + put_bit(strchr(castling_rights, 'Q') != NULL); + } + } + + // padding stuff +#if 1 + if (bits_left != 8) + ++pos_len; +#endif + + // and the header byte + position[0] = pos_len; + + if (strcmp(castling_rights, "-") != 0) + position[0] |= 0x40; + if (ep_any) + position[0] |= 0x20; + +#if 1 + // dump + { + int i; + for (i = 0; i < pos_len; ++i) { + printf("%02x ", position[i]); + } + printf("\n"); + } +#endif +} + +int search_pos(unsigned c, char *result) +{ + char buf[4]; + unsigned char pagebuf[4096]; + unsigned page; + unsigned page_len; + + lseek(cto_fd, c * 4 + 16, SEEK_SET); + + read(cto_fd, buf, 4); + page = htonl(*((unsigned *)buf)); + if (page == -1) + return 0; + + lseek(ctg_fd, page * 4096 + 4096, SEEK_SET); + read(ctg_fd, pagebuf, 4096); + + // search the page + { + int pos = 4; + int page_end = htons(*((short *)(pagebuf + 2))); + + while (pos < page_end) { + if (pagebuf[pos] != position[0] || + memcmp(pagebuf + pos, position, pos_len) != 0) { + // no match, skip through + pos += pagebuf[pos] & 0x1f; + pos += pagebuf[pos]; + pos += 33; + continue; + } + pos += pagebuf[pos] & 0x1f; + memcpy(result, pagebuf + pos, pagebuf[pos] + 33); + return 1; + } + } + + return 0; +} + +int lookup_position(char *pos, unsigned len, char *result) +{ + int hash = gen_hash(position, pos_len); + int n; + + for (n = 0; n < 0x7fffffff; n = 2 * n + 1) { + unsigned c = (hash & n) + n; + + // FIXME: adjust these bounds + if (c < 0x80e0) + continue; + + if (search_pos(c, result)) + return 1; + + if (c >= 0x1fd00) + break; + } + + return 0; +} + +struct moveenc { + char encoding; + char piece; + int num; + int forward, right; +}; +struct moveenc movetable[] = { + 0x00, 'P', 5, 1, 1, + 0x01, 'N', 2, -1, -2, + 0x04, 'P', 2, 1, 0, + 0x05, 'Q', 1, 1, 0, + 0x06, 'P', 4, 1, -1, + 0x09, 'B', 2, 6, 6, + 0x0a, 'K', 1, -1, 0, + 0x0c, 'P', 1, 1, -1, + 0x0d, 'B', 1, 3, 3, + 0x0e, 'R', 2, 0, 3, + 0x0f, 'N', 1, -1, -2, + 0x12, 'B', 1, 7, 7, + 0x13, 'K', 1, 1, 0, + 0x14, 'P', 8, 1, 1, + 0x15, 'B', 1, 5, 5, + 0x18, 'P', 7, 1, 0, + 0x1b, 'B', 1, 1, -1, + 0x1d, 'B', 2, 7, 7, + 0x21, 'R', 2, 0, 7, + 0x22, 'B', 2, 2, -2, + 0x24, 'P', 8, 1, -1, + 0x26, 'B', 1, 7, -7, + 0x27, 'P', 3, 1, -1, + 0x28, 'Q', 1, 5, 5, + 0x29, 'Q', 1, 0, 6, + 0x2a, 'N', 2, -2, 1, + 0x2d, 'P', 6, 1, 1, + 0x2e, 'B', 1, 1, 1, + 0x2f, 'Q', 1, 0, 1, + 0x30, 'N', 2, -2, -1, + 0x31, 'Q', 1, 0, 3, + 0x32, 'B', 2, 5, 5, + 0x34, 'N', 1, 2, 1, + 0x36, 'N', 1, 1, 2, + 0x37, 'Q', 1, 4, 0, + 0x39, 'Q', 1, 0, 5, + 0x3a, 'B', 1, 6, 6, + 0x3c, 'B', 1, 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, + 0x50, 'R', 1, 6, 0, + 0x52, 'R', 1, 0, 6, + 0x54, 'B', 2, 1, -1, + 0x55, 'P', 3, 1, 0, + 0x5c, 'P', 7, 1, 1, + 0x5f, 'P', 5, 2, 0, + 0x61, 'Q', 1, 6, 6, + 0x62, 'P', 2, 2, 0, + 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, + 0x72, 'B', 2, 7, -7, + 0x74, 'Q', 1, 0, 2, + 0x79, 'B', 2, 6, -6, + 0x7a, 'R', 1, 3, 0, + 0x7b, 'R', 2, 6, 0, + 0x7c, 'P', 3, 1, 1, + 0x7d, 'R', 2, 1, 0, + 0x7e, 'Q', 1, 3, -3, + 0x7f, 'R', 1, 0, 1, + 0x80, 'Q', 1, 6, -6, + 0x81, 'R', 1, 1, 0, + 0x82, 'P', 6, 1, -1, + 0x85, 'N', 1, 2, -1, + 0x86, 'R', 1, 0, 7, + 0x87, 'R', 1, 5, 0, + 0x8a, 'N', 1, -2, 1, + 0x8b, 'P', 1, 1, 1, + 0x8c, 'K', 1, -1, -1, + 0x8f, 'Q', 1, 0, 7, + 0x94, 'Q', 1, 3, 0, + 0x96, 'P', 2, 1, 1, + 0x97, 'K', 1, 0, -1, + 0x98, 'R', 1, 0, 3, + 0x99, 'R', 1, 4, 0, + 0x9a, 'Q', 1, 6, 0, + 0x9b, 'P', 3, 2, 0, + 0x9d, 'Q', 1, 2, 0, + 0x9f, 'B', 2, 4, -4, + 0xa2, 'Q', 1, 2, 2, + 0xa3, 'P', 8, 1, 0, + 0xa5, 'R', 2, 5, 0, + 0xa9, 'R', 2, 0, 2, + 0xad, 'R', 2, 0, 4, + 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, + 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, + 0xc7, 'P', 7, 1, -1, + 0xc8, 'P', 7, 2, 0, + 0xca, 'B', 2, 3, -3, + 0xcb, 'P', 6, 1, 0, + 0xcc, 'B', 2, 5, -5, + 0xcd, 'R', 1, 0, 2, + 0xcf, 'P', 4, 1, 0, + 0xd1, 'P', 2, 1, -1, + 0xd2, 'N', 2, 1, 2, + 0xd3, 'N', 2, 1, -2, + 0xd7, 'Q', 1, 1, -1, + 0xd8, 'R', 2, 0, 6, + 0xd9, 'Q', 1, 2, -2, + 0xda, 'N', 1, -2, -1, + 0xdb, 'P', 1, 2, 0, + 0xde, 'P', 5, 1, -1, + 0xdf, 'K', 1, 1, -1, + 0xe0, 'N', 2, -1, 2, + 0xe1, 'R', 1, 7, 0, + 0xe3, 'R', 2, 3, 0, + 0xe5, 'Q', 1, 0, 4, + 0xe6, 'P', 4, 2, 0, + 0xe7, 'Q', 1, 4, 4, + 0xe8, 'R', 1, 2, 0, + 0xe9, 'N', 1, -1, 2, + 0xeb, 'P', 4, 1, 1, + 0xec, 'P', 1, 1, 0, + 0xed, 'Q', 1, 7, 7, + 0xef, 'R', 1, 0, 4, + 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 +}; + +int find_piece(char *board, char piece, int num) +{ + int y, x; + for (x = 0; x < 8; ++x) { + for (y = 0; y < 8; ++y) { + if (board[(7-y) * 8 + x] != piece) + continue; + if (--num == 0) + return (y * 8 + x); + } + } + + fprintf(stderr, "Couldn't find piece '%c' number %u\n", piece, num); +} + +void execute_move(char *board, char *castling_rights, int inverted, char *ep_square, int from_square, int to_square) +{ + int black_ks, black_qs, white_ks, white_qs; + + // fudge + from_square = (7 - (from_square / 8)) * 8 + (from_square % 8); + to_square = (7 - (to_square / 8)) * 8 + (to_square % 8); + + // compute the new castling rights + black_ks = (strchr(castling_rights, 'k') != NULL); + black_qs = (strchr(castling_rights, 'q') != NULL); + white_ks = (strchr(castling_rights, 'K') != NULL); + white_qs = (strchr(castling_rights, 'Q') != NULL); + + if (board[from_square] == 'K') { + if (inverted) + black_ks = black_qs = 0; + else + white_ks = white_qs = 0; + } else if (board[from_square] == 'R') { + if (inverted) { + if (from_square == 0) // a1 + black_qs = 0; + else if (from_square == 7 * 8 + 0) // a8 + black_ks = 0; + } else { + if (from_square == 0) // a1 + white_qs = 0; + else if (from_square == 7 * 8 + 0) // a8 + white_ks = 0; + } + } + + if ((black_ks | black_qs | white_ks | white_qs) == 0) { + strcpy(castling_rights, "-"); + } else { + strcpy(castling_rights, ""); + + if (white_ks) + strcat(castling_rights, "K"); + if (white_qs) + strcat(castling_rights, "Q"); + if (black_ks) + strcat(castling_rights, "k"); + if (black_qs) + strcat(castling_rights, "q"); + } + + // 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); + } else { + strcpy(ep_square, "-"); + } + + // is this move an en passant capture? + if (board[from_square] == 'P' && board[to_square] == ' ' && + (to_square - from_square == -9 || to_square - from_square == -7)) { + board[to_square + 8] = ' '; + } + + // make the move + board[to_square] = board[from_square]; + board[from_square] = ' '; + + if (board[to_square] == 'K' && to_square - from_square == 2) { + // short castling + board[to_square - 1] = 'R'; + board[to_square + 1] = ' '; + } else if (board[to_square] == 'K' && to_square - from_square == -2) { + // long castling + board[to_square + 1] = 'R'; + board[to_square - 2] = ' '; + } + +#if 0 + // dump the board + { + int y, x; + printf("\n\n"); + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + putchar(board[y * 8 + x]); + } + putchar('\n'); + } + } + printf("cr='%s' ep='%s'\n", castling_rights, ep_square); +#endif +} + +void dump_move(char *board, char *castling_rights, char *ep_col, int invert, char move, char annotation) +{ + int i; + char newboard[64], nkr[5], neps[3]; + for (i = 0; i < sizeof(movetable)/sizeof(movetable[0]); ++i) { + int from_square, from_row, from_col; + int to_square, to_row, to_col; + int ret; + char result[256]; + + if (move != movetable[i].encoding) + continue; + + from_square = find_piece(board, movetable[i].piece, movetable[i].num); + from_row = from_square / 8; + from_col = from_square % 8; + + 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; + + // 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 + printf("%c%u%c%u,", + "abcdefgh"[from_square % 8], from_square / 8 + 1, + "abcdefgh"[to_square % 8], to_square / 8 + 1); + + // annotation + switch (annotation) { + case 0x00: + break; + case 0x01: + printf("!"); + break; + case 0x02: + printf("?"); + break; + case 0x03: + printf("!!"); + break; + case 0x04: + printf("??"); + break; + case 0x05: + printf("!?"); + break; + case 0x06: + printf("?!"); + break; + case 0x08: + printf(" (only move)"); + break; + case 0x16: + printf(" (zugzwang)"); + break; + default: + printf(" (unknown status 0x%02x)", 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); +} + +void dump_info(char *board, char *castling_rights, char *ep_col, int invert, char *result) +{ + int book_moves = result[0] >> 1; + int i; + + printf(",,"); + output_stats(result, !invert); + + for (i = 0; i < book_moves; ++i) { + dump_move(board, castling_rights, ep_col, invert, result[i * 2 + 1], result[i * 2 + 2]); + } +} + +int main(int argc, char **argv) +{ + // encode the position + char board[64], result[256]; + int invert = 0; + 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); + } + +#if 0 + // dump the board + { + int y, x; + for (y = 0; y < 8; ++y) { + for (x = 0; x < 8; ++x) { + putchar(board[y * 8 + x]); + } + putchar('\n'); + } + } +#endif + + encode_position(board, invert, argv[3], argv[4]); + ret = lookup_position(position, pos_len, result); + if (!ret) { + printf("Not found in book.\n"); + exit(1); + } + + dump_info(board, argv[3], argv[4], invert, result); +} + diff --git a/remoteglot.pl b/remoteglot.pl index 16a4f8d..655a9ae 100755 --- a/remoteglot.pl +++ b/remoteglot.pl @@ -18,9 +18,10 @@ use warnings; # Configuration my $server = "freechess.org"; -my $target = "224"; +my $target = "Sessse"; # my $engine = "/usr/games/toga2"; -my $engine = "wine Rybkav2.3.2a.mp.w32.exe"; +# my $engine = "wine Rybkav2.3.2a.mp.w32.exe"; +my $engine = "~/microwine-0.2/microwine Rybkav2.3.2a.mp.x64.exe"; my $telltarget = undef; # undef to be silent my @tell_intervals = (5, 20, 60, 120, 240, 480, 960); # after each move my $uci_assume_full_compliance = 1; # dangerous :-) @@ -67,10 +68,10 @@ while () { uciprint("setoption name UCI_AnalyseMode value true"); # uciprint("setoption name Preserve Analysis value true"); -uciprint("setoption name NalimovPath value c:\\nalimov"); +uciprint("setoption name NalimovPath value /srv/tablebase"); uciprint("setoption name NalimovUsage value Rarely"); uciprint("setoption name Hash value 1024"); -uciprint("setoption name MultiPV value 3"); +uciprint("setoption name MultiPV value 2"); # uciprint("setoption name Contempt value 1000"); # uciprint("setoption name Outlook value Ultra Optimistic"); uciprint("ucinewgame"); @@ -382,7 +383,7 @@ sub style12_to_fen { sub prettyprint_pv { my ($board, @pvs) = @_; - + if (scalar @pvs == 0 || !defined($pvs[0])) { return (); } @@ -652,6 +653,8 @@ sub output_screen { $text .= "\n\n"; } + $text .= book_info($pos_calculating->{'fen'}, $pos_calculating->{'board'}, $pos_calculating->{'toplay'}); + if ($last_text ne $text) { print ""; # clear the screen print $text; @@ -953,3 +956,55 @@ sub long_score { return undef; } + +my %book_cache = (); +sub book_info { + my ($fen, $board, $toplay) = @_; + + if (exists($book_cache{$fen})) { + return $book_cache{$fen}; + } + + my $ret = `./booklook $fen`; + return "[$fen]" if ($ret =~ /Not found/ || $ret eq ''); + + my @moves = (); + + for my $m (split /\n/, $ret) { + my ($move, $annotation, $win, $draw, $lose, $rating, $rating_div) = split /,/, $m; + + my $pmove; + if ($move eq '') { + $pmove = '(current)'; + } else { + ($pmove) = prettyprint_pv($board, $move); + $pmove .= $annotation; + } + + my $score; + if ($toplay eq 'W') { + $score = 1.0 * $win + 0.5 * $draw + 0.0 * $lose; + } else { + $score = 0.0 * $win + 0.5 * $draw + 1.0 * $lose; + } + my $n = $win + $draw + $lose; + + my $percent; + if ($n == 0) { + $percent = " "; + } else { + $percent = sprintf "%4u%%", int(100.0 * $score / $n + 0.5); + } + + push @moves, [ $pmove, $n, $percent, $rating ]; + } + + @moves[1..$#moves] = sort { $b->[2] cmp $a->[2] } @moves[1..$#moves]; + + my $text = "Book moves:\n\n Perf. N Rating\n\n"; + for my $m (@moves) { + $text .= sprintf " %-10s %s %6u %4s\n", $m->[0], $m->[2], $m->[1], $m->[3] + } + + return $text; +} -- 2.39.2