Example #1
0
        /// Book::binary_search() takes a book key as input, and does a binary search
        /// through the book file for the given key. File stream current position is set
        /// to the leftmost book entry with the same key as the input.
        private static void binary_search(UInt64 key, UInt64 size, BinaryReader br)
        {
            UInt64    low, high, mid;
            BookEntry e = new BookEntry();

            low  = 0;
            high = (ulong)(size - 1);

            Debug.Assert(low <= high);

            while (low < high)
            {
                mid = (low + high) / 2;

                Debug.Assert(mid >= low && mid < high);

                br.BaseStream.Seek((long)(mid * SIZE_OF_BOOKENTRY), SeekOrigin.Begin);
                Read(ref e, br);

                if (key <= e.key)
                {
                    high = mid;
                }
                else
                {
                    low = mid + 1;
                }
            }

            Debug.Assert(low == high);

            br.BaseStream.Seek((long)(low * SIZE_OF_BOOKENTRY), SeekOrigin.Begin);
        }
Example #2
0
        private static bool Read(ref BookEntry e, BinaryReader br)
        {
            if (br.BaseStream.Length == br.BaseStream.Position)
            {
                return(false);
            }

            byte[] t = br.ReadBytes((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);
        }
Example #3
0
        private static bool Read(ref BookEntry e, BinaryReader br)
        {
            if (br.BaseStream.Length == br.BaseStream.Position) return false;

            byte[] t = br.ReadBytes((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;
        }
Example #4
0
        /// Book::binary_search() takes a book key as input, and does a binary search
        /// through the book file for the given key. File stream current position is set
        /// to the leftmost book entry with the same key as the input.
        private static void binary_search(UInt64 key, UInt64 size, BinaryReader br)
        {
            UInt64 low, high, mid;
            BookEntry e = new BookEntry();

            low = 0;
            high = (ulong)(size - 1);

            Debug.Assert(low <= high);

            while (low < high)
            {
                mid = (low + high) / 2;

                Debug.Assert(mid >= low && mid < high);

                br.BaseStream.Seek((long)(mid * SIZE_OF_BOOKENTRY), SeekOrigin.Begin);
                Read(ref e, br);

                if (key <= e.key)
                    high = mid;
                else
                    low = mid + 1;
            }

            Debug.Assert(low == high);

            br.BaseStream.Seek((long)(low * SIZE_OF_BOOKENTRY), SeekOrigin.Begin);
        }
Example #5
0
        /// Book::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.
        internal static Move probe(Position pos, string filename, bool pickBest)
        {
            #if PORTABLE

            #region DLL book

            if (bookNotExists) { return MoveC.MOVE_NONE; }

            BookEntry e = new BookEntry();
            UInt16 best = 0;
            uint sum = 0;
            Move move = MoveC.MOVE_NONE;
            UInt64 key = book_key(pos);

            try
            {
                System.Reflection.Assembly bookAssembly = System.Reflection.Assembly.Load("PortfishBook");
                using (Stream fs = bookAssembly.GetManifestResourceStream("PortfishBook.book.bin"))
                {
                    UInt64 size = (UInt64)(fs.Length / SIZE_OF_BOOKENTRY);
                    using (BinaryReader br = new BinaryReader(fs))
                    {
                        binary_search(key, size, br);
                        while (Read(ref e, br) && (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 ((RKiss.rand() % sum < e.count)
                                || (pickBest && e.count == best))
                            {
                                move = e.move;
                            }
                        }
                    }
                }
            }
            catch(System.IO.FileNotFoundException)
            {
                bookNotExists = true;
                return MoveC.MOVE_NONE;
            }

            #endregion

            #else

            #region File system read

            if (!System.IO.File.Exists(filename)) return MoveC.MOVE_NONE;

            BookEntry e = new BookEntry();
            UInt16 best = 0;
            uint sum = 0;
            Move move = MoveC.MOVE_NONE;
            UInt64 key = book_key(pos);

            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                UInt64 size = (UInt64)(fs.Length / SIZE_OF_BOOKENTRY);
                using (BinaryReader br = new BinaryReader(fs))
                {
                    binary_search(key, size, br);
                    while (Read(ref e, br) && (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) && (RKiss.rand() % sum < e.count))
                            || (pickBest && e.count == best))
                        {
                            move = e.move;
                        }
                    }
                    br.Close();
                }
                fs.Close();
            }

            #endregion

            #endif

            if (move != 0)
            {
                // 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 = Utils.make_promotion(Utils.from_sq(move), Utils.to_sq(move), (pt + 1));
                }

                // Add 'special move' flags and verify it is legal
                MList mlist = MListBroker.GetObject(); mlist.pos = 0;
                Movegen.generate_legal(pos, mlist.moves, ref mlist.pos);
                for (int i = 0; i < mlist.pos; i++)
                {
                    if (move == (mlist.moves[i].move & 0x3FFF))
                    {
                        Move retval = mlist.moves[i].move;
                        MListBroker.Free();
                        return retval;
                    }
                }
                MListBroker.Free();
            }

            return MoveC.MOVE_NONE;
        }
Example #6
0
        /// Book::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.
        internal static Move probe(Position pos, string filename, bool pickBest)
        {
#if PORTABLE
            #region DLL book

            if (bookNotExists)
            {
                return(MoveC.MOVE_NONE);
            }

            BookEntry e    = new BookEntry();
            UInt16    best = 0;
            uint      sum  = 0;
            Move      move = MoveC.MOVE_NONE;
            UInt64    key  = book_key(pos);

            try
            {
                System.Reflection.Assembly bookAssembly = System.Reflection.Assembly.Load("PortfishBook");
                using (Stream fs = bookAssembly.GetManifestResourceStream("PortfishBook.book.bin"))
                {
                    UInt64 size = (UInt64)(fs.Length / SIZE_OF_BOOKENTRY);
                    using (BinaryReader br = new BinaryReader(fs))
                    {
                        binary_search(key, size, br);
                        while (Read(ref e, br) && (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 ((RKiss.rand() % sum < e.count) ||
                                (pickBest && e.count == best))
                            {
                                move = e.move;
                            }
                        }
                    }
                }
            }
            catch (System.IO.FileNotFoundException)
            {
                bookNotExists = true;
                return(MoveC.MOVE_NONE);
            }

            #endregion
#else
            #region File system read

            if (!System.IO.File.Exists(filename))
            {
                return(MoveC.MOVE_NONE);
            }

            BookEntry e    = new BookEntry();
            UInt16    best = 0;
            uint      sum  = 0;
            Move      move = MoveC.MOVE_NONE;
            UInt64    key  = book_key(pos);

            using (FileStream fs = new FileStream(filename, FileMode.Open))
            {
                UInt64 size = (UInt64)(fs.Length / SIZE_OF_BOOKENTRY);
                using (BinaryReader br = new BinaryReader(fs))
                {
                    binary_search(key, size, br);
                    while (Read(ref e, br) && (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) && (RKiss.rand() % sum < e.count)) ||
                            (pickBest && e.count == best))
                        {
                            move = e.move;
                        }
                    }
                    br.Close();
                }
                fs.Close();
            }

            #endregion
#endif

            if (move != 0)
            {
                // 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 = Utils.make_promotion(Utils.from_sq(move), Utils.to_sq(move), (pt + 1));
                }

                // Add 'special move' flags and verify it is legal
                MList mlist = MListBroker.GetObject(); mlist.pos = 0;
                Movegen.generate_legal(pos, mlist.moves, ref mlist.pos);
                for (int i = 0; i < mlist.pos; i++)
                {
                    if (move == (mlist.moves[i].move & 0x3FFF))
                    {
                        Move retval = mlist.moves[i].move;
                        MListBroker.Free();
                        return(retval);
                    }
                }
                MListBroker.Free();
            }

            return(MoveC.MOVE_NONE);
        }
Example #7
0
        /// PolyglotBook::find_first() takes a book key as input, and does a binary search
        /// through the book file for the given key. File stream current position is set
        /// to the leftmost book entry with the same key as the input.
        private static Key find_first(ulong key, ulong size, BinaryReader br)
        {
            ulong low, high, mid;
            var e = new BookEntry();

            low = 0;
            high = size - 1;

            Debug.Assert(low <= high);

            while (low < high)
            {
                mid = (low + high) / 2;

                Debug.Assert(mid >= low && mid < high);

                br.BaseStream.Seek((long)(mid * SIZE_OF_BOOKENTRY), SeekOrigin.Begin);
                Read(ref e, br);

                if (key <= e.key)
                {
                    high = mid;
                }
                else
                {
                    low = mid + 1;
                }
            }

            Debug.Assert(low == high);

            br.BaseStream.Seek((long)(low * SIZE_OF_BOOKENTRY), SeekOrigin.Begin);

            return low;
        }