Ejemplo n.º 1
0
        // start_thinking() wakes up the main thread sleeping in MainThread::idle_loop()
        // so to start a new search, then returns immediately.
        public void start_thinking(Position pos, LimitsType limits, StateStackPtr states)
        {
            wait_for_think_finished();

            Search.SearchTime = Time.now(); // As early as possible

            Search.Signals.stopOnPonderhit = Search.Signals.firstRootMove = false;
            Search.Signals.stop = Search.Signals.failedLowAtRoot = false;

            Search.RootMoves.Clear();
            Search.RootPos = pos;
            Search.Limits = limits;

            if (states.Count > 0) // If we don't set a new position, preserve current state
            {
                Search.SetupStates = states; // Ownership transfer here                
                //Debug.Assert(states==null);
            }

            for (MoveList it = new MoveList(pos, GenTypeS.LEGAL); it.move()!= 0; ++it)
                if (limits.searchmoves.Count == 0
                    || Misc.existSearchMove(limits.searchmoves, it.move()))
                    Search.RootMoves.Add(new RootMove(it.move()));

            main().thinking = true;
            main().notify_one(); // Starts main thread
        }
Ejemplo n.º 2
0
 public MoveList(Position pos, GenType T)
 {
     cur              = 0;
     mlist            = new ExtMove[Types.MAX_MOVES];
     last             = MoveList.generate(pos, mlist, 0, T);
     mlist[last].move = MoveS.MOVE_NONE;
 }
Ejemplo n.º 3
0
        /// move_from_uci() takes a position and a string representing a move in
        /// simple coordinate notation and returns an equivalent legal Move if any.
        public static Move move_from_uci(Position pos, string str)
        {
            if (str.Length == 5)
            { // Junior could send promotion piece in uppercase
                char[] strChar = str.ToCharArray();
                strChar[4] = char.ToLower(strChar[4]);
                str        = new String(strChar);
            }

            for (MoveList it = new MoveList(pos, GenTypeS.LEGAL); it.mlist[it.cur].move != MoveS.MOVE_NONE; ++it)
            {
                if (str == move_to_uci(it.move(), pos.is_chess960() != 0))
                {
                    return(it.move());
                }
            }

            return(MoveS.MOVE_NONE);
        }
Ejemplo n.º 4
0
        /// 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);
        }
Ejemplo n.º 5
0
        /// generate_next_stage() generates, scores and sorts the next bunch of moves,
        /// when there are no more moves to try for the current stage.
        public void generate_next_stage()
        {
            cur = 0;

            switch (++stage)
            {
            case StagesS.CAPTURES_S1:
            case StagesS.CAPTURES_S3:
            case StagesS.CAPTURES_S4:
            case StagesS.CAPTURES_S5:
            case StagesS.CAPTURES_S6:
                end = MoveList.generate(pos, moves, 0, GenTypeS.CAPTURES);
                score_captures();
                return;

            case StagesS.KILLERS_S1:
                cur = Types.MAX_MOVES;
                end = cur + 2;

                moves[Types.MAX_MOVES].move     = ss.killers0;
                moves[Types.MAX_MOVES + 1].move = ss.killers1;
                moves[Types.MAX_MOVES + 2].move = moves[Types.MAX_MOVES + 3].move = MoveS.MOVE_NONE;
                moves[Types.MAX_MOVES + 4].move = moves[Types.MAX_MOVES + 5].move = MoveS.MOVE_NONE;

                // Please note that following code is racy and could yield to rare (less
                // than 1 out of a million) duplicated entries in SMP case. This is harmless.

                // Be sure countermoves are different from killers
                for (int i = 0; i < 2; ++i)
                {
                    if (countermoves[i] != moves[cur].move &&
                        countermoves[i] != moves[cur + 1].move)
                    {
                        moves[end++].move = countermoves[i];
                    }
                }

                // Be sure followupmoves are different from killers and countermoves
                for (int i = 0; i < 2; ++i)
                {
                    if (followupmoves[i] != moves[cur].move &&
                        followupmoves[i] != moves[cur + 1].move &&
                        followupmoves[i] != moves[cur + 2].move &&
                        followupmoves[i] != moves[cur + 3].move)
                    {
                        moves[end++].move = followupmoves[i];
                    }
                }

                return;

            case StagesS.QUIETS_1_S1:
                endQuiets = end = MoveList.generate(pos, moves, 0, GenTypeS.QUIETS);
                score_quiets();
                end = partition(moves, cur, end);
                insertion_sort(moves, cur, end);
                return;

            case StagesS.QUIETS_2_S1:
                cur = end;
                end = endQuiets;
                if (depth >= 3 * DepthS.ONE_PLY)
                {
                    insertion_sort(moves, cur, end);
                }
                return;

            case StagesS.BAD_CAPTURES_S1:
                // Just pick them in reverse order to get MVV/LVA ordering
                cur = Types.MAX_MOVES - 1;
                end = endBadCaptures;
                return;

            case StagesS.EVASIONS_S2:
                end = MoveList.generate(pos, moves, 0, GenTypeS.EVASIONS);
                if (end > 1)
                {
                    score_evasions();
                }
                return;

            case StagesS.QUIET_CHECKS_S3:
                end = MoveList.generate(pos, moves, 0, GenTypeS.QUIET_CHECKS);
                return;

            case StagesS.EVASION:
            case StagesS.QSEARCH_0:
            case StagesS.QSEARCH_1:
            case StagesS.PROBCUT:
            case StagesS.RECAPTURE:
                stage = StagesS.STOP;
                end   = cur + 1;
                break;

            case StagesS.STOP:
                end = cur + 1;     // Avoid another next_phase() call
                return;

            default:
                Debug.Assert(false);
                break;
            }
        }