예제 #1
0
 public void Go(Parser parser)
 {
     BestMoves.Clear();
     if (Bound.ParseBounds(parser, MovePosition))
     {
         StartTask((state) => startSearch((Position?)state, SearchMode.BestMove), MovePosition);
     }
 }
예제 #2
0
    public Eval Search(Draft wDraft, Eval mAlpha, Eval mBeta,
                       Move moveExcluded = Move.Undefined) {
      var moves = PseudoMoves;
      BestMoves.Clear();                //[Required]

      #region Test for Draw
      if (IsDraw()) {                   //[Note]setDraw50() must be called after tryMove(), below.
        State.IncEvalType(EvalType.Exact);
        return eval();
      }
      #endregion

      #region Test for entry into Quiet Search
      var bInCheck = InCheck();
      if (bInCheck) {                   // Check Extension
        if (extended(ref wDraft, SearchExtensions.Check))
          AtomicIncrement(ref State.CheckExtCount);
      }

      //
      // Depth is tested here, rather than in the PVS recursion case,
      // because search also recurses from the heuristic cases below.
      //
      var wDepth = depth(wDraft);       // InCheck Adjusted Depth
      if (wDepth < 1) {
#if Quiescence
        return quiet(mAlpha, mBeta);
#else
        return boundValue(eval(), mAlpha, mBeta);
#endif
      }
      #endregion

      #region Transposition Table Lookup
#if TraceVal
      var bTrace = IsTrace();
      if (IsTrace()) {                  //[Note]CurrentMove Undefined
        Display($"Search(Depth = {wDepth})");
      }
#endif
      Debug.Assert(mAlpha < mBeta, "Alpha must be less than Beta");

      var goodMoves = new List<GoodMove>(nFirstCapacity);
      var bFoundValue = probeXP(wDepth, mAlpha, mBeta, moveExcluded, goodMoves,
                                out Move moveFound, out Eval mValueFound, out EvalType etFound);
      // Variations updated iff bFoundValue
      if (bFoundValue) {
        // moveFound not always defined for EvalType.Upper [Fail Low]
        if (isDefinite(moveFound)) {    //[Safe]Also prevent unexpected EmptyMove
#if DebugMove
          unpackMove1(moveFound, out sq sqFrom, out sq sqTo, out Piece piece, out Piece promotion, out Boolean bCapture);
          //unpackMove2(moveFound, out sq sqFrom, out sq sqTo, out Piece piece, out Piece promotion, out Piece capture, out Boolean bCastles, out Boolean bCapture);
#endif
          if (IsMovePosition)           // Pass empty BestMoves, at top level
            AddPV(mAlpha, mValueFound, moveFound, BestMoves);
#if AddBestMoves
          BestMoves.Add(moveFound);     // Safe to update BestMoves now
#endif
        }

        return mValueFound;
      }
      #endregion

      #region Heuristic Tests
      var bReduced = (FlagsMode & ModeFlags.Reduced) != 0;
      if (bReduced)
        AtomicIncrement(ref State.ReducedTotal);

      var bTestSingular = false;
      var bPruneQuiet = false;
      var bPVS = (FlagsMode & ModeFlags.ZWS) == 0;
      var bMoveExcluded = isDefined(moveExcluded);
      var wReducedDraft = reduceShallow(wDraft);// Draft for Heuristic Searches

      if (!bInCheck) {
        var mStand = standpatval(mValueFound, etFound);

        if (!bPVS) {
          if (prune(wDraft, wDepth, mAlpha, mBeta, mValueFound, etFound, bMoveExcluded, out Eval mPrunedValue))
            return mPrunedValue;
        }

        if (!bReduced) {
          //[Conditional]
          threat(ref wDraft, ref wReducedDraft, ref wDepth);
        }

        // Determine whether Futility Pruning should be performed at Frontier Nodes:
        if (State.IsFutility && 0 < wDepth) {
          var bNonMateWindow = -MateMin < mAlpha && mBeta < MateMin;
          var bNonEndGame = (FlagsEG & EGFlags.EndGame) == 0;
          if (bNonMateWindow && bNonEndGame) {
            var nMargin = wDepth - 1;
            if (nMargin < FutilityMargin.Length)
              bPruneQuiet = mStand + FutilityMargin[nMargin] <= mAlpha;
          }
        }                               // Futility Pruning

#if SingularExtension
        bTestSingular = wSingularDepthMin <= wDepth &&
                        EvalUndefined < mValueFound &&
                        //[Test]More inclusion performs better than less!
                        Abs(mValueFound) < mQueenWeight &&
                        isDefined(moveFound) && !(bReduced || bMoveExcluded) &&
                        canExtend(vSingular);   //[Ergo]child.canExtend(vSingular) below
#endif
      }                                 // !bInCheck
      #endregion

      #region Generate Moves
      //
      // The "go searchmoves" UCI command sets SearchMoves
      // to restrict the set of candidate moves at the Root:
      //
      if (SearchMoves is not null && SearchMoves.Count > 0) {
        moves.Clear();
        moves.AddRange(SearchMoves);
#if DebugSearchMoves
        var sb = new StringBuilder("SearchMoves:");
        sb.MapMoves(Extension.AppendPACN, moves, State.Rule);
        LogLine(sb.ToString());
#endif
      }
예제 #3
0
        protected Eval quiet(Eval mAlpha, Eval mBeta)
        {
            var moves = PseudoMoves;

            BestMoves.Clear();          //[Required]

            #region Test for Draw
            if (IsDraw())               //[Note]setDraw50() will not be called below
            {
                State.IncEvalType(EvalType.Exact);
#if TransposeQuiet
                return(eval());
#else
                return(boundValue(eval(), mAlpha, mBeta));
#endif
            }
            #endregion

            #region Transposition Table Lookup
#if TraceVal
            var bTrace = IsTrace();
            if (bTrace)
            {
                const String sLabel = "quiet()";
                Display(sLabel);        //[Note]Undefined CurrentMove
            }
#endif
            // BestMoves updated iff bFoundValue
            if (probeQxnt(mAlpha, mBeta, out Move moveFound, out Eval mValueFound, out EvalType etFound))
            {
                // moveFound not always defined for EvalType.Upper [Fail Low]
                if (isDefinite(moveFound)) //[Safe]Also prevent unexpected EmptyMove
                {
#if DebugMove
                    unpackMove1(moveFound, out sq sqFrom, out sq sqTo, out Piece piece, out Piece promotion, out Boolean bCapture);
                    //unpackMove2(moveFound, out sq sqFrom, out sq sqTo, out Piece piece, out Piece promotion, out Piece capture, out Boolean bCastles, out Boolean bCapture);
#endif
#if AddBestMoves
                    BestMoves.Add(moveFound);
#endif
                }

                return(mValueFound);
            }
            #endregion

            #region Move Loop Initializaton
#if QuietCheck || QuietMate
            var bInCheck = InCheck();
#endif
            var et = EvalType.Upper;    //[Init]Fail Low is the default assumption
                                        // Stand Pat (tests Draw Flags)
            var mStand = standpatval(mValueFound, etFound);

            var moveBest = Move.Undefined; //[Init]
            var mValue   = EvalUndefined;
            var mBest    = EvalUndefined;

            var bStandPat = mAlpha /*+ mStandPatWeight*/ < mStand;
            if (bStandPat)
            {
                mBest = mStand;

                if (mAlpha < mBest)
                {
                    mAlpha = mBest;
                }
            }
            #endregion

            if (mBeta <= mAlpha)
            {
                //[Test]return boundValue(mBest, mAlpha, mBeta);
            }
            else
            {
                #region Generate Moves
                if (SearchMoves is not null && SearchMoves.Count > 0)
                {
                    moves.Clear();
                    moves.AddRange(SearchMoves);
#if DebugSearchMoves
                    var sb = new StringBuilder("SearchMoves:");
                    sb.MapMoves(Extension.AppendPACN, moves, State.Rule);
                    sb.FlushLine();
#endif
                }