mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 17:19:36 +00:00
Space inflate book.cpp
Also document most interesting parts. No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
92ca97d121
commit
afadc33fb4
3 changed files with 120 additions and 100 deletions
115
src/book.cpp
115
src/book.cpp
|
@ -49,6 +49,10 @@ Book OpeningBook;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/// Book entry size in bytes
|
||||||
|
const int EntrySize = 16;
|
||||||
|
|
||||||
|
|
||||||
/// Random numbers from PolyGlot, used to compute book hash keys.
|
/// Random numbers from PolyGlot, used to compute book hash keys.
|
||||||
|
|
||||||
const uint64_t Random64[781] = {
|
const uint64_t Random64[781] = {
|
||||||
|
@ -324,13 +328,6 @@ namespace {
|
||||||
const int RandomTurn = 780;
|
const int RandomTurn = 780;
|
||||||
|
|
||||||
|
|
||||||
/// Convert pieces to the range 0..1
|
|
||||||
|
|
||||||
const int PieceTo12[] = {
|
|
||||||
0, 0, 2, 4, 6, 8, 10, 0, 0, 1, 3, 5, 7, 9, 11
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Prototypes
|
/// Prototypes
|
||||||
|
|
||||||
uint64_t book_key(const Position& pos);
|
uint64_t book_key(const Position& pos);
|
||||||
|
@ -355,7 +352,7 @@ namespace {
|
||||||
Book::Book() : bookSize(0) {}
|
Book::Book() : bookSize(0) {}
|
||||||
|
|
||||||
|
|
||||||
/// Book::open() opens a book file with a given file name.
|
/// Book::open() opens a book file with a given file name
|
||||||
|
|
||||||
void Book::open(const std::string& fName) {
|
void Book::open(const std::string& fName) {
|
||||||
|
|
||||||
|
@ -364,19 +361,21 @@ void Book::open(const std::string &fName) {
|
||||||
if (!bookFile.is_open())
|
if (!bookFile.is_open())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// get the book size in number of entries
|
||||||
bookFile.seekg(0, std::ios::end);
|
bookFile.seekg(0, std::ios::end);
|
||||||
bookSize = bookFile.tellg() / 16;
|
bookSize = bookFile.tellg() / EntrySize;
|
||||||
bookFile.seekg(0, std::ios::beg);
|
bookFile.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
if (!bookFile.good())
|
if (!bookFile.good())
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to open book file " << fileName << std::endl;
|
std::cerr << "Failed to open book file " << fileName << std::endl;
|
||||||
|
bookFile.close();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Book::close() closes the currently open book file.
|
/// Book::close() closes the currently open book file
|
||||||
|
|
||||||
void Book::close() {
|
void Book::close() {
|
||||||
|
|
||||||
|
@ -398,7 +397,7 @@ bool Book::is_open() const {
|
||||||
|
|
||||||
const std::string Book::file_name() const {
|
const std::string Book::file_name() const {
|
||||||
|
|
||||||
return bookFile.is_open() ? fileName : "";
|
return is_open() ? fileName : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,33 +405,41 @@ const std::string Book::file_name() const {
|
||||||
/// MOVE_NONE if no book move is found.
|
/// MOVE_NONE if no book move is found.
|
||||||
|
|
||||||
Move Book::get_move(const Position& pos) const {
|
Move Book::get_move(const Position& pos) const {
|
||||||
if(this->is_open()) {
|
|
||||||
int bestMove = 0, bestScore = 0, move, score;
|
if (!is_open())
|
||||||
|
return MOVE_NONE;
|
||||||
|
|
||||||
|
int bookMove = 0, scoresSum = 0;
|
||||||
uint64_t key = book_key(pos);
|
uint64_t key = book_key(pos);
|
||||||
BookEntry entry;
|
BookEntry entry;
|
||||||
|
|
||||||
for(int i = this->find_key(key); i < bookSize; i++) {
|
// Choose a book move among the possible moves for the given position
|
||||||
this->read_entry(entry, i);
|
for (int i = find_key(key); i < bookSize; i++)
|
||||||
|
{
|
||||||
|
read_entry(entry, i);
|
||||||
if (entry.key != key)
|
if (entry.key != key)
|
||||||
break;
|
break;
|
||||||
move = entry.move;
|
|
||||||
score = entry.count;
|
int score = entry.count;
|
||||||
|
|
||||||
assert(score > 0);
|
assert(score > 0);
|
||||||
|
|
||||||
bestScore += score;
|
// Choose book move according to its score. If a move has a very
|
||||||
if(int(genrand_int32() % bestScore) < score)
|
// high score it has more probability to be choosen then a one with
|
||||||
bestMove = move;
|
// lower score. Note that first entry is always chosen.
|
||||||
|
scoresSum += score;
|
||||||
|
if (int(genrand_int32() % scoresSum) < score)
|
||||||
|
bookMove = entry.move;
|
||||||
}
|
}
|
||||||
|
if (!bookMove)
|
||||||
|
return MOVE_NONE;
|
||||||
|
|
||||||
if(bestMove != 0) {
|
|
||||||
MoveStack moves[256];
|
MoveStack moves[256];
|
||||||
int n, j;
|
int n = generate_legal_moves(pos, moves);
|
||||||
n = generate_legal_moves(pos, moves);
|
for (int j = 0; j < n; j++)
|
||||||
for(j = 0; j < n; j++)
|
if ((int(moves[j].move) & 07777) == bookMove)
|
||||||
if((int(moves[j].move) & 07777) == bestMove)
|
|
||||||
return moves[j].move;
|
return moves[j].move;
|
||||||
}
|
|
||||||
}
|
|
||||||
return MOVE_NONE;
|
return MOVE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,6 +450,7 @@ Move Book::get_move(const Position &pos) const {
|
||||||
/// found in the book file, bookSize is returned.
|
/// found in the book file, bookSize is returned.
|
||||||
|
|
||||||
int Book::find_key(uint64_t key) const {
|
int Book::find_key(uint64_t key) const {
|
||||||
|
|
||||||
int left, right, mid;
|
int left, right, mid;
|
||||||
BookEntry entry;
|
BookEntry entry;
|
||||||
|
|
||||||
|
@ -452,22 +460,21 @@ int Book::find_key(uint64_t key) const {
|
||||||
|
|
||||||
assert(left <= right);
|
assert(left <= right);
|
||||||
|
|
||||||
while(left < right) {
|
while(left < right)
|
||||||
|
{
|
||||||
mid = (left + right) / 2;
|
mid = (left + right) / 2;
|
||||||
|
|
||||||
assert(mid >= left && mid < right);
|
assert(mid >= left && mid < right);
|
||||||
|
|
||||||
this->read_entry(entry, mid);
|
read_entry(entry, mid);
|
||||||
|
|
||||||
if (key <= entry.key)
|
if (key <= entry.key)
|
||||||
right = mid;
|
right = mid;
|
||||||
else
|
else
|
||||||
left = mid + 1;
|
left = mid + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(left == right);
|
assert(left == right);
|
||||||
|
|
||||||
this->read_entry(entry, left);
|
read_entry(entry, left);
|
||||||
|
|
||||||
return (entry.key == key)? left : bookSize;
|
return (entry.key == key)? left : bookSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,12 +486,13 @@ int Book::find_key(uint64_t key) const {
|
||||||
void Book::read_entry(BookEntry& entry, int n) const {
|
void Book::read_entry(BookEntry& entry, int n) const {
|
||||||
|
|
||||||
assert(n >= 0 && n < bookSize);
|
assert(n >= 0 && n < bookSize);
|
||||||
assert(bookFile.is_open());
|
assert(is_open());
|
||||||
|
|
||||||
bookFile.seekg(n*16, std::ios_base::beg);
|
bookFile.seekg(n * EntrySize, std::ios_base::beg);
|
||||||
if (!bookFile.good())
|
if (!bookFile.good())
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to read book entry at index " << n << std::endl;
|
std::cerr << "Failed to read book entry at index " << n << std::endl;
|
||||||
|
bookFile.close();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
entry.key = read_integer64(bookFile);
|
entry.key = read_integer64(bookFile);
|
||||||
|
@ -502,15 +510,18 @@ void Book::read_entry(BookEntry& entry, int n) const {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
uint64_t book_key(const Position& pos) {
|
uint64_t book_key(const Position& pos) {
|
||||||
|
|
||||||
uint64_t result = 0ULL;
|
uint64_t result = 0ULL;
|
||||||
|
|
||||||
for(Color c = WHITE; c <= BLACK; c++) {
|
for (Color c = WHITE; c <= BLACK; c++)
|
||||||
|
{
|
||||||
Bitboard b = pos.pieces_of_color(c);
|
Bitboard b = pos.pieces_of_color(c);
|
||||||
Square s;
|
|
||||||
Piece p;
|
while (b != EmptyBoardBB)
|
||||||
while(b != EmptyBoardBB) {
|
{
|
||||||
s = pop_1st_bit(&b);
|
Square s = pop_1st_bit(&b);
|
||||||
p = pos.piece_on(s);
|
Piece p = pos.piece_on(s);
|
||||||
|
|
||||||
assert(piece_is_ok(p));
|
assert(piece_is_ok(p));
|
||||||
assert(color_of_piece(p) == c);
|
assert(color_of_piece(p) == c);
|
||||||
|
|
||||||
|
@ -521,39 +532,46 @@ namespace {
|
||||||
result ^= book_castle_key(pos);
|
result ^= book_castle_key(pos);
|
||||||
result ^= book_ep_key(pos);
|
result ^= book_ep_key(pos);
|
||||||
result ^= book_color_key(pos);
|
result ^= book_color_key(pos);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t book_piece_key(Piece p, Square s) {
|
uint64_t book_piece_key(Piece p, Square s) {
|
||||||
|
|
||||||
|
/// Convert pieces to the range 0..11
|
||||||
|
static const int PieceTo12[] = { 0, 0, 2, 4, 6, 8, 10, 0, 0, 1, 3, 5, 7, 9, 11 };
|
||||||
|
|
||||||
return Random64[RandomPiece + (PieceTo12[int(p)]^1) * 64 + int(s)];
|
return Random64[RandomPiece + (PieceTo12[int(p)]^1) * 64 + int(s)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t book_castle_key(const Position& pos) {
|
uint64_t book_castle_key(const Position& pos) {
|
||||||
|
|
||||||
uint64_t result = 0ULL;
|
uint64_t result = 0ULL;
|
||||||
|
|
||||||
if (pos.can_castle_kingside(WHITE))
|
if (pos.can_castle_kingside(WHITE))
|
||||||
result ^= Random64[RandomCastle+0];
|
result ^= Random64[RandomCastle+0];
|
||||||
|
|
||||||
if (pos.can_castle_queenside(WHITE))
|
if (pos.can_castle_queenside(WHITE))
|
||||||
result ^= Random64[RandomCastle+1];
|
result ^= Random64[RandomCastle+1];
|
||||||
|
|
||||||
if (pos.can_castle_kingside(BLACK))
|
if (pos.can_castle_kingside(BLACK))
|
||||||
result ^= Random64[RandomCastle+2];
|
result ^= Random64[RandomCastle+2];
|
||||||
|
|
||||||
if (pos.can_castle_queenside(BLACK))
|
if (pos.can_castle_queenside(BLACK))
|
||||||
result ^= Random64[RandomCastle+3];
|
result ^= Random64[RandomCastle+3];
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t book_ep_key(const Position& pos) {
|
uint64_t book_ep_key(const Position& pos) {
|
||||||
return (pos.ep_square() == SQ_NONE)?
|
return (pos.ep_square() == SQ_NONE ? 0ULL : Random64[RandomEnPassant + square_file(pos.ep_square())]);
|
||||||
0ULL : Random64[RandomEnPassant + square_file(pos.ep_square())];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t book_color_key(const Position& pos) {
|
uint64_t book_color_key(const Position& pos) {
|
||||||
return (pos.side_to_move() == WHITE)? Random64[RandomTurn] : 0ULL;
|
return (pos.side_to_move() == WHITE ? Random64[RandomTurn] : 0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -578,11 +596,12 @@ namespace {
|
||||||
|
|
||||||
if (!file.good())
|
if (!file.good())
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to read " << size << " bytes from book file"
|
std::cerr << "Failed to read " << size << " bytes from book file" << std::endl;
|
||||||
<< std::endl;
|
file.close();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
// Numbers are stored in little endian format
|
|
||||||
|
// Numbers are stored on disk in big endian format
|
||||||
uint64_t n = 0ULL;
|
uint64_t n = 0ULL;
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
n = (n << 8) + (unsigned char)buf[i];
|
n = (n << 8) + (unsigned char)buf[i];
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
# include "dos.h"
|
# include "dos.h"
|
||||||
|
|
||||||
static int gettimeofday(struct timeval* tp, struct timezone*)
|
static int gettimeofday(struct timeval* tp, struct timezone*)
|
||||||
{
|
{
|
||||||
SYSTEMTIME systime;
|
SYSTEMTIME systime;
|
||||||
|
|
Loading…
Add table
Reference in a new issue