// ThreadsManager::start_searching() wakes up the main thread sleeping in // main_loop() so to start a new search, then returns immediately. internal static void start_searching(Position pos, LimitsType limits, List <Move> searchMoves) { wait_for_search_finished(); Search.SearchTime.Reset(); Search.SearchTime.Start(); // As early as possible Search.SignalsStopOnPonderhit = Search.SignalsFirstRootMove = false; Search.SignalsStop = Search.SignalsFailedLowAtRoot = false; Search.RootPosition.copy(pos); Search.Limits = limits; Search.RootMoves.Clear(); MList mlist = MListBroker.GetObject(); mlist.pos = 0; Movegen.generate_legal(pos, mlist.moves, ref mlist.pos); for (int i = 0; i < mlist.pos; i++) { Move move = mlist.moves[i].move; if ((searchMoves.Count == 0) || Utils.existSearchMove(searchMoves, move)) { Search.RootMoves.Add(new RootMove(move)); } } MListBroker.Free(); main_thread().do_sleep = false; main_thread().wake_up(); }
/// Mate with KX vs K. This function is used to evaluate positions with /// King and plenty of material vs a lone king. It simply gives the /// attacking side a bonus for driving the defending king towards the edge /// of the board, and for keeping the distance between the two kings small. /// KXK internal static Value Endgame_KXK(Color strongerSide, Position pos) { Color weakerSide = strongerSide ^ 1; Debug.Assert(pos.non_pawn_material(weakerSide) == ValueC.VALUE_ZERO); Debug.Assert(pos.piece_count(weakerSide, PieceTypeC.PAWN) == ValueC.VALUE_ZERO); // Stalemate detection with lone king MList mlist = MListBroker.GetObject(); mlist.pos = 0; Movegen.generate_legal(pos, mlist.moves, ref mlist.pos); bool any = mlist.pos > 0; MListBroker.Free(); if (pos.sideToMove == weakerSide && !pos.in_check() && !any) { return ValueC.VALUE_DRAW; } Square winnerKSq = pos.king_square(strongerSide); Square loserKSq = pos.king_square(weakerSide); Value result = pos.non_pawn_material(strongerSide) + pos.piece_count(strongerSide, PieceTypeC.PAWN) * Constants.PawnValueEndgame + MateTable[loserKSq] + DistanceBonus[Utils.square_distance(winnerKSq, loserKSq)]; if (pos.piece_count(strongerSide, PieceTypeC.QUEEN)!=0 || pos.piece_count(strongerSide, PieceTypeC.ROOK)!=0 || pos.bishop_pair(strongerSide)) { result += ValueC.VALUE_KNOWN_WIN; } return strongerSide == pos.sideToMove ? result : -result; }
/// 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); }
internal static void Warmup() { // Bench 128 4 17 yields: // CheckInfoBroker: 140 (4/32/40/32/32) // EvalInfoBroker: 16 (4/4/4/4) // SwapListBroker: 16 (4/4/4/4) // MovesSearchedBroker: 120 (28/36/28/28) // PositionBroker: 32 (8/8/8/8) // StateInfoArrayBroker: 16 (4/4/4/4) // MListBroker: 20 (4/4/4/4/4) // LoopStackBroker: 32 (8/8/8/8) // MovePickerBroker: 136 (32/40/32/32) // StateInfoBroker: 132 (32/36/32/32) // Specific allocation not to overallocate memory for nothing int i, brokerSize; // Reusing brokers brokerSize = 40; for (i = 0; i < brokerSize; i++) { CheckInfoBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { CheckInfoBroker.Free(); } brokerSize = 4; for (i = 0; i < brokerSize; i++) { EvalInfoBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { EvalInfoBroker.Free(); } brokerSize = 4; for (i = 0; i < brokerSize; i++) { SwapListBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { SwapListBroker.Free(); } brokerSize = 36; for (i = 0; i < brokerSize; i++) { MovesSearchedBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { MovesSearchedBroker.Free(); } brokerSize = 8; for (i = 0; i < brokerSize; i++) { PositionBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { PositionBroker.Free(); } brokerSize = 4; for (i = 0; i < brokerSize; i++) { StateInfoArrayBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { StateInfoArrayBroker.Free(); } brokerSize = 4; for (i = 0; i < brokerSize; i++) { MListBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { MListBroker.Free(); } brokerSize = 36; for (i = 0; i < brokerSize; i++) { StateInfoBroker.GetObject(); } for (i = 0; i < brokerSize; i++) { StateInfoBroker.Free(); } // Recycling brokers brokerSize = 8; LoopStack[] arrLoopStack = new LoopStack[brokerSize]; for (i = 0; i < brokerSize; i++) { arrLoopStack[i] = LoopStackBroker.GetObject(); } for (i = brokerSize - 1; i >= 0; i--) { LoopStackBroker.Free(arrLoopStack[i]); } brokerSize = 40; MovePicker[] arrMovePicker = new MovePicker[brokerSize]; for (i = 0; i < brokerSize; i++) { arrMovePicker[i] = MovePickerBroker.GetObject(); } for (i = brokerSize - 1; i >= 0; i--) { MovePickerBroker.Free(arrMovePicker[i]); } }