internal static MList GetObject() { #if WINDOWS_RT int slotID = Environment.CurrentManagedThreadId & Constants.BROKER_SLOT_MASK; #else int slotID = System.Threading.Thread.CurrentThread.ManagedThreadId & Constants.BROKER_SLOT_MASK; #endif if (_cnt[slotID] == _pool[slotID].Length) { int poolLength = _pool[slotID].Length; MList[] temp = new MList[poolLength + Constants.BrokerCapacity]; Array.Copy(_pool[slotID], temp, poolLength); for (int i = 0; i < Constants.BrokerCapacity; i++) { temp[poolLength + i] = new MList(); } _pool[slotID] = temp; } return(_pool[slotID][_cnt[slotID]++]); }
/// 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 WINDOWS_RT #region DLL book (local) 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); using (Stream fs = typeof(Engine).GetTypeInfo().Assembly.GetManifestResourceStream("SethRocks.book.bin")) { if (fs == null) { bookNotExists = true; return(MoveC.MOVE_NONE); } 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; } } } } #endregion #elif 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("SethRocksBook"); using (Stream fs = bookAssembly.GetManifestResourceStream("SethRocksBook.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); }