protected Eval storeQXP(Eval mValue, EvalType et, Move moveBest = Move.Undefined) { Trace.Assert(EvalUndefined < mValue, "storeQXP(EvalUndefined)"); traceVal("storeQXP", mValue, et); //[Conditional] State.IncEvalType(et); var mAdjusted = creditMate(mValue, SearchPly); if (IsFinal()) { Trace.Assert(!isDefined(moveBest), "moveBest defined in a Final position."); moveBest = Move.EmptyMove; } #if DebugMoveColor if (isDefinite(moveBest)) { var bWTM = WTM(); var bWhiteMove = (moveBest & Move.WTM) != 0; if (bWTM != bWhiteMove) { Debug.Assert(bWTM == bWhiteMove, "WTM != WhiteMove [storeQXP]"); DisplayCurrent("storeQXP()"); } } #endif #if QXPHash128 var store = new QuietPosition(Hash, State.MovePly, HashPawn, mAdjusted, et, moveBest); #else var store = new QuietPosition(Hash, State.MovePly, mAdjusted, et, moveBest); #endif State.QXPTank.Save(store); return(mValue); }
protected Eval storeXP(Depth wDepth, Eval mValue, EvalType et, Move moveBest = Move.Undefined, Move moveExcluded = Move.Undefined) // 10 MHz { Trace.Assert(EvalUndefined < mValue, "storeXP(EvalUndefined)"); traceVal("storeXP", mValue, et); //[Conditional] State.IncEvalType(et); var qDynamic = DynamicHash(moveExcluded); var mAdjusted = creditMate(mValue, SearchPly); if (IsFinal()) { Trace.Assert(!isDefined(moveBest), "moveBest defined in a Final position."); moveBest = Move.EmptyMove; } #if DebugMoveColor if (isDefinite(moveBest)) { var bWTM = WTM(); var bWhiteMove = (moveBest & Move.WTM) != 0; if (bWTM != bWhiteMove) { Debug.Assert(bWTM == bWhiteMove, "WTM != WhiteMove [storeXP]"); DisplayCurrent("storeXP()"); } } #endif #if XPHash128 #if XPMoveTypes var store = new Transposition(qDynamic, HashPawn, MoveTypeOrdering, State.MovePly, wDepth, mAdjusted, et, moveBest); #else var store = new Transposition(qDynamic, HashPawn, State.MovePly, wDepth, mAdjusted, et, moveBest); #endif #else // XPHash128 #if XPMoveTypes var store = new Transposition(qDynamic, MoveTypeOrdering, State.MovePly, wDepth, mAdjusted, et, moveBest); #else var store = new Transposition(qDynamic, State.MovePly, wDepth, mAdjusted, et, moveBest); #endif #endif State.XPTank.Save(store); return(mValue); }
protected Eval storeXPM(Depth wDepth, Eval mValue, EvalType et, Move moveBest = Move.Undefined, Move moveExcluded = Move.Undefined) // 10 MHz { Trace.Assert(EvalUndefined < mValue, "storeXPM(EvalUndefined)"); traceVal("storeXPM", mValue, et); //[Conditional] State.IncEvalType(et); #if XPMCompositionHash || DebugMoveColor var bWTM = WTM(); #endif #if XPMCompositionHash UInt32 wPly = State.MovePly; var nSide = bWTM ? 0 : 1; var uMemoHash = compositionHash(bWTM); var qDynamic = (Hashcode)(uMemoHash * wPly + nSide); #else var qDynamic = DynamicHash(moveExcluded); #endif var mAdjusted = creditMate(mValue, SearchPly); if (IsFinal()) { Trace.Assert(!isDefined(moveBest), "moveBest defined in a Final position."); moveBest = Move.EmptyMove; } #if DebugMoveColor if (isDefinite(moveBest)) { var bWhiteMove = (moveBest & Move.WTM) != 0; if (bWTM != bWhiteMove) { Debug.Assert(bWTM == bWhiteMove, "WTM != WhiteMove [storeXPM]"); DisplayCurrent("storeXPM()"); } } #endif #if XPHash128 var store = new PositionMove(qDynamic, HashPawn, State.MovePly, wDepth, mAdjusted, et, moveBest); #else var store = new PositionMove(qDynamic, State.MovePly, wDepth, mAdjusted, et, moveBest); #endif State.XPMTank.Save(store); return(mValue); }
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 }
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 }