/// find_first() takes a book key as input, and does a binary search through /// the book file for the given key. Returns the index of the leftmost book /// entry with the same key as the input. public int find_first(Key key) { int low = 0, mid, high = (int)(stream.Length / SIZE_OF_BOOKENTRY) - 1; PolyglotBook.Entry e = new PolyglotBook.Entry();; Debug.Assert(low <= high); while (low < high) { mid = (low + high) / 2; Debug.Assert(mid >= low && mid < high); stream.Seek(mid * SIZE_OF_BOOKENTRY, SeekOrigin.Begin); read(ref e); if (key <= e.key) { high = mid; } else { low = mid + 1; } } Debug.Assert(low == high); return(low); }
/// operator>>() reads sizeof(T) chars from the file's binary byte stream and /// converts them in a number of type T. A Polyglot book stores numbers in /// big-endian format. public bool read(ref PolyglotBook.Entry e) { if (stream.Length == stream.Position) { return(false); } byte[] t = new byte[SIZE_OF_BOOKENTRY]; stream.Read(t, 0, (int)SIZE_OF_BOOKENTRY); e.key = (((UInt64)t[0]) << 56) | (((UInt64)t[1]) << 48) | (((UInt64)t[2]) << 40) | (((UInt64)t[3]) << 32) | (((UInt64)t[4]) << 24) | (((UInt64)t[5]) << 16) | (((UInt64)t[6]) << 8) | (((UInt64)t[7]) << 0); e.move = (UInt16)( (((UInt64)t[8]) << 8) | (((UInt64)t[9]) << 0)); e.count = (UInt16)( (((UInt64)t[10]) << 8) | (((UInt64)t[11]) << 0)); e.learn = (UInt32)( (((UInt64)t[12]) << 24) | (((UInt64)t[13]) << 16) | (((UInt64)t[14]) << 8) | (((UInt64)t[15]) << 0)); return(true); }
/// probe() tries to find a book move for the given position. If no move is /// found returns MOVE_NONE. If pickBest is true returns always the highest /// rated move, otherwise randomly chooses one, based on the move score. public Move probe(Position pos, string fName, bool pickBest) { if (fName == null || (fileName != fName && !open(fName))) { return(MoveS.MOVE_NONE); } PolyglotBook.Entry e = new PolyglotBook.Entry(); UInt16 best = 0; uint sum = 0; Move move = MoveS.MOVE_NONE; Key key = polyglot_key(pos); stream.Seek(find_first(key) * SIZE_OF_BOOKENTRY, SeekOrigin.Begin); while (read(ref e) && e.key == key) { best = Math.Max(best, e.count); sum += e.count; // Choose book move according to its score. If a move has a very // high score it has higher probability to be choosen than a move // with lower score. Note that first entry is always chosen. if ((sum != 0 && ((((uint)RKiss.rand64()) % sum) < e.count)) || (pickBest && e.count == best)) { move = (e.move); } } if (move == 0) { return(MoveS.MOVE_NONE); } // A PolyGlot book move is encoded as follows: // // bit 0- 5: destination square (from 0 to 63) // bit 6-11: origin square (from 0 to 63) // bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4) // // Castling moves follow "king captures rook" representation. So in case book // move is a promotion we have to convert to our representation, in all the // other cases we can directly compare with a Move after having masked out // the special Move's flags (bit 14-15) that are not supported by PolyGlot. int pt = (move >> 12) & 7; if (pt != 0) { move = Types.make(Types.from_sq(move), Types.to_sq(move), MoveTypeS.PROMOTION, (pt + 1)); } // Add 'special move' flags and verify it is legal for (MoveList ml = new MoveList(pos, GenTypeS.LEGAL); ml.mlist[ml.cur].move != MoveS.MOVE_NONE; ++ml) { if (move == (ml.move() ^ Types.type_of_move(ml.move()))) { return(ml.move()); } } return(MoveS.MOVE_NONE); }