本文整理汇总了C#中Position.key方法的典型用法代码示例。如果您正苦于以下问题:C# Position.key方法的具体用法?C# Position.key怎么用?C# Position.key使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Position
的用法示例。
在下文中一共展示了Position.key方法的6个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: insert_pv_in_tt
/// RootMove::insert_pv_in_tt() is called at the end of a search iteration, and
/// inserts the PV back into the TT. This makes sure the old PV moves are searched
/// first, even if the old TT entries have been overwritten.
internal void insert_pv_in_tt(Position pos)
{
var st = new StateInfoWrapper();
foreach (var m in pv)
{
Debug.Assert(new MoveList(GenType.LEGAL, pos).contains(m));
bool ttHit;
var tte = TranspositionTable.probe(pos.key(), out ttHit);
if (!ttHit || tte.move() != m) // Don't overwrite correct entries
{
tte.save(
pos.key(),
Value.VALUE_NONE,
Bound.BOUND_NONE,
Depth.DEPTH_NONE,
m,
Value.VALUE_NONE,
TranspositionTable.generation());
}
var current = st[st.current];
st++;
pos.do_move(m, current, pos.gives_check(m, new CheckInfo(pos)));
}
for (var i = pv.Count; i > 0;)
{
pos.undo_move(pv[--i]);
}
}
示例2: update
internal void update(Position pos, List<MoveT> newPv)
{
Debug.Assert(newPv.Count >= 3);
// Keep track of how many times in a row 3rd ply remains stable
stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0;
if (pv[0] != newPv[0] || pv[1] != newPv[1] || pv[2] != newPv[2])
{
pv[0] = newPv[0];
pv[1] = newPv[1];
pv[2] = newPv[2];
var st = new StateInfo[2];
pos.do_move(newPv[0], st[0], pos.gives_check(newPv[0], new CheckInfo(pos)));
pos.do_move(newPv[1], st[1], pos.gives_check(newPv[1], new CheckInfo(pos)));
expectedPosKey = pos.key();
pos.undo_move(newPv[1]);
pos.undo_move(newPv[0]);
}
}
示例3: extract_ponder_from_tt
/// RootMove::extract_ponder_from_tt() is called in case we have no ponder move before
/// exiting the search, for instance in case we stop the search during a fail high at
/// root. We try hard to have a ponder move to return to the GUI, otherwise in case of
/// 'ponder on' we have nothing to think on.
internal bool extract_ponder_from_tt(Position pos)
{
var st = new StateInfo();
bool ttHit;
Debug.Assert(pv.Count == 1);
pos.do_move(pv[0], st, pos.gives_check(pv[0], new CheckInfo(pos)));
var tte = TranspositionTable.probe(pos.key(), out ttHit);
pos.undo_move(pv[0]);
if (ttHit)
{
var m = tte.move(); // Local copy to be SMP safe
if (new MoveList(GenType.LEGAL, pos).contains(m))
{
pv.Add(m);
return true;
}
}
return false;
}
示例4: search
// search<>() is the main search function for both PV and non-PV nodes and for
// normal and SplitPoint nodes. When called just after a split point the search
// is simpler because we have already probed the hash table, done a null move
// search, and searched the first move before splitting, so we don't have to
// repeat all this work again. We also don't need to store anything to the hash
// table here: This is taken care of after we return from the split point.
private static ValueT search(NodeType NT, bool SpNode, Position pos, StackArrayWrapper ss, ValueT alpha, ValueT beta,
Depth depth, bool cutNode)
{
Utils.WriteToLog($"search(NT={(int) NT}, SpNode={(SpNode ? 1 : 0)}, pos={pos.key()}, ss, alpha={alpha}, beta={beta}, depth={(int) depth}, cutNode={(cutNode ? 1 : 0)})");
var RootNode = NT == NodeType.Root;
var PvNode = RootNode || NT == NodeType.PV;
Debug.Assert(-Value.VALUE_INFINITE <= alpha && alpha < beta && beta <= Value.VALUE_INFINITE);
Debug.Assert(PvNode || (alpha == beta - 1));
Debug.Assert(depth > Depth.DEPTH_ZERO);
var st = new StateInfo();
TTEntry tte;
SplitPoint splitPoint = null;
ulong posKey = 0;
MoveT ttMove, move, excludedMove, bestMove;
ValueT bestValue, value, ttValue, eval;
bool ttHit;
int moveCount = 0;
int quietCount = 0;
var stack = ss[ss.current];
var stackPlus1 = ss[ss.current + 1];
var stackPlus2 = ss[ss.current + 2];
var stackMinus1 = ss[ss.current - 1];
var stackMinus2 = ss[ss.current - 2];
// Step 1. Initialize node
var thisThread = pos.this_thread();
bool inCheck = pos.checkers() != 0;
if (SpNode)
{
splitPoint = stack.splitPoint;
bestMove = Move.Create(splitPoint.bestMove);
bestValue = Value.Create(splitPoint.bestValue);
tte = new TTEntry();
ttMove = excludedMove = Move.MOVE_NONE;
ttValue = Value.VALUE_NONE;
Debug.Assert(splitPoint.bestValue > -Value.VALUE_INFINITE && splitPoint.moveCount > 0);
goto moves_loop;
}
moveCount = quietCount = stack.moveCount = 0;
bestValue = -Value.VALUE_INFINITE;
stack.ply = stackMinus1.ply + 1;
// Used to send selDepth info to GUI
if (PvNode && thisThread.maxPly < stack.ply)
thisThread.maxPly = stack.ply;
if (!RootNode)
{
// Step 2. Check for aborted search and immediate draw
if (Signals.stop || pos.is_draw() || stack.ply >= _.MAX_PLY)
return stack.ply >= _.MAX_PLY && !inCheck
? Eval.evaluate(false, pos)
: DrawValue[pos.side_to_move()];
// Step 3. Mate distance pruning. Even if we mate at the next move our score
// would be at best mate_in(ss.ply+1), but if alpha is already bigger because
// a shorter mate was found upward in the tree then there is no need to search
// because we will never beat the current alpha. Same logic but with reversed
// signs applies also in the opposite condition of being mated instead of giving
// mate. In this case return a fail-high score.
alpha = Value.Create(Math.Max(Value.mated_in(stack.ply), alpha));
beta = Value.Create(Math.Min(Value.mate_in(stack.ply + 1), beta));
if (alpha >= beta)
return alpha;
}
Debug.Assert(0 <= stack.ply && stack.ply < _.MAX_PLY);
stack.currentMove = stack.ttMove = stackPlus1.excludedMove = bestMove = Move.MOVE_NONE;
stackPlus1.skipEarlyPruning = false;
stackPlus1.reduction = Depth.DEPTH_ZERO;
stackPlus2.killers0 = stackPlus2.killers1 = Move.MOVE_NONE;
// Step 4. Transposition table lookup
// We don't want the score of a partial search to overwrite a previous full search
// TT value, so we use a different position key in case of an excluded move.
excludedMove = stack.excludedMove;
posKey = excludedMove != 0 ? pos.exclusion_key() : pos.key();
tte = TranspositionTable.probe(posKey, out ttHit);
stack.ttMove = ttMove = RootNode ? RootMoves[(int) PVIdx].pv[0] : ttHit ? tte.move() : Move.MOVE_NONE;
ttValue = ttHit ? value_from_tt(tte.value(), stack.ply) : Value.VALUE_NONE;
// At non-PV nodes we check for a fail high/low. We don't prune at PV nodes
if (!PvNode
&& ttHit
&& tte.depth() >= depth
//.........这里部分代码省略.........
示例5: id_loop
// id_loop() is the main iterative deepening loop. It calls search() repeatedly
// with increasing depth until the allocated thinking time has been consumed,
// user stops the search, or the maximum search depth is reached.
private static void id_loop(Position pos)
{
var stack = new Stack[_.MAX_PLY + 4];
for (var idx = 0; idx < stack.Length; idx++)
{
stack[idx] = new Stack();
}
var ss = new StackArrayWrapper(stack, 2); // To allow referencing (ss-2) and (ss+2)
ValueT alpha, delta;
var easyMove = EasyMove.get(pos.key());
EasyMove.clear();
//TODO: need to memset?
//Math.Memset(ss - 2, 0, 5 * sizeof(Stack));
var depth = Depth.DEPTH_ZERO;
BestMoveChanges = 0;
var bestValue = delta = alpha = -Value.VALUE_INFINITE;
var beta = Value.VALUE_INFINITE;
TranspositionTable.new_search();
var multiPV = uint.Parse(OptionMap.Instance["MultiPV"].v);
var skill = new Skill(int.Parse(OptionMap.Instance["Skill Level"].v));
// When playing with strength handicap enable MultiPV search that we will
// use behind the scenes to retrieve a set of possible moves.
if (skill.enabled())
{
multiPV = Math.Max(multiPV, 4);
multiPV = Math.Max(multiPV, 4);
multiPV = Math.Max(multiPV, 4);
}
multiPV = (uint) Math.Min(multiPV, RootMoves.Count);
// Iterative deepening loop until requested to stop or target depth reached;
while (++depth < _.MAX_PLY && !Signals.stop && (Limits.depth == 0 || depth <= Limits.depth))
{
// Age out PV variability metric
BestMoveChanges *= 0.5;
// Save the last iteration's scores before first PV line is searched and
// all the move scores except the (new) PV are set to -VALUE_INFINITE.
foreach (var rm in RootMoves)
{
rm.previousScore = rm.score;
}
// MultiPV loop. We perform a full root search for each PV line
for (PVIdx = 0; PVIdx < multiPV && !Signals.stop; ++PVIdx)
{
// Reset aspiration window starting size
if (depth >= 5*Depth.ONE_PLY_C)
{
delta = Value.Create(16);
alpha = Value.Create(Math.Max(RootMoves[(int) PVIdx].previousScore - delta, -Value.VALUE_INFINITE));
beta = Value.Create(Math.Min(RootMoves[(int) PVIdx].previousScore + delta, Value.VALUE_INFINITE));
}
// Start with a small aspiration window and, in the case of a fail
// high/low, re-search with a bigger window until we're not failing
// high/low anymore.
while (true)
{
bestValue = search(NodeType.Root, false, pos, ss, alpha, beta, depth, false);
// Bring the best move to the front. It is critical that sorting
// is done with a stable algorithm because all the values but the
// first and eventually the new best one are set to -VALUE_INFINITE
// and we want to keep the same order for all the moves except the
// new PV that goes to the front. Note that in case of MultiPV
// search the already searched PV lines are preserved.
//TODO: Check for stable sort replacement
Utils.stable_sort(RootMoves, (int) PVIdx, RootMoves.Count);
//std::stable_sort(RootMoves.begin() + PVIdx, RootMoves.end());
// Write PV back to transposition table in case the relevant
// entries have been overwritten during the search.
for (var i = 0; i <= PVIdx; ++i)
{
RootMoves[i].insert_pv_in_tt(pos);
}
// If search has been stopped break immediately. Sorting and
// writing PV back to TT is safe because RootMoves is still
// valid, although it refers to previous iteration.
if (Signals.stop)
{
break;
}
//.........这里部分代码省略.........
示例6: qsearch
private static ValueT qsearch(NodeType NT, bool InCheck, Position pos, StackArrayWrapper ss, ValueT alpha, ValueT beta,
Depth depth)
{
Utils.WriteToLog($"qsearch(NT={(int) NT}, InCheck={(InCheck ? 1 : 0)}, pos={pos.key()}, ss, alpha={alpha}, beta={beta}, depth={(int) depth})");
var PvNode = NT == NodeType.PV;
Debug.Assert(NT == NodeType.PV || NT == NodeType.NonPV);
Debug.Assert(InCheck == (pos.checkers() != 0));
Debug.Assert(alpha >= -Value.VALUE_INFINITE && alpha < beta && beta <= Value.VALUE_INFINITE);
Debug.Assert(PvNode || (alpha == beta - 1));
Debug.Assert(depth <= Depth.DEPTH_ZERO_C);
var currentStack = ss[ss.current];
var nextStack = ss[ss.current+1];
var previousStack = ss[ss.current - 1];
var oldAlpha = 0;
if (PvNode)
{
oldAlpha = alpha; // To flag BOUND_EXACT when eval above alpha and no available moves
nextStack.pv = new List<MoveT>() { Move.MOVE_NONE };
currentStack.pv[0] = Move.MOVE_NONE;
}
currentStack.currentMove = Move.MOVE_NONE;
currentStack.ply = previousStack.ply + 1;
var currentPly = currentStack.ply;
// Check for an instant draw or if the maximum ply has been reached
if (pos.is_draw() || currentPly >= _.MAX_PLY)
return currentPly >= _.MAX_PLY && !InCheck
? Eval.evaluate(false, pos)
: DrawValue[pos.side_to_move()];
Debug.Assert(0 <= currentPly && currentPly < _.MAX_PLY);
// Decide whether or not to include checks: this fixes also the type of
// TT entry depth that we are going to use. Note that in qsearch we use
// only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
var ttDepth = InCheck || (int)depth >= Depth.DEPTH_QS_CHECKS_C
? Depth.DEPTH_QS_CHECKS
: Depth.DEPTH_QS_NO_CHECKS;
// Transposition table lookup
bool ttHit;
var posKey = pos.key();
var tte = TranspositionTable.probe(posKey, out ttHit);
var ttMove = ttHit ? tte.move() : Move.MOVE_NONE;
var ttValue = ttHit ? value_from_tt(tte.value(), currentPly) : Value.VALUE_NONE;
if (!PvNode
&& ttHit
&& tte.depth() >= ttDepth
&& ttValue != Value.VALUE_NONE // Only in case of TT access race
&& ((ttValue >= beta ? (tte.bound() & Bound.BOUND_LOWER) : (tte.bound() & Bound.BOUND_UPPER))) != 0)
{
currentStack.currentMove = ttMove; // Can be MOVE_NONE
return ttValue;
}
ValueT bestValue;
ValueT futilityBase;
// Evaluate the position statically
if (InCheck)
{
currentStack.staticEval = Value.VALUE_NONE;
bestValue = futilityBase = -Value.VALUE_INFINITE;
}
else
{
if (ttHit)
{
// Never assume anything on values stored in TT
if ((currentStack.staticEval = bestValue = tte.eval()) == Value.VALUE_NONE)
currentStack.staticEval = bestValue = Eval.evaluate(false, pos);
// Can ttValue be used as a better position evaluation?
if (ttValue != Value.VALUE_NONE)
if ((tte.bound() & (ttValue > bestValue ? Bound.BOUND_LOWER : Bound.BOUND_UPPER)) != 0)
bestValue = ttValue;
}
else
currentStack.staticEval = bestValue =
previousStack.currentMove != Move.MOVE_NULL
? Eval.evaluate(false, pos)
: -previousStack.staticEval + 2*Eval.Tempo;
// Stand pat. Return immediately if static value is at least beta
if (bestValue >= beta)
{
if (!ttHit)
tte.save(pos.key(), value_to_tt(bestValue, currentPly), Bound.BOUND_LOWER,
Depth.DEPTH_NONE, Move.MOVE_NONE, currentStack.staticEval, TranspositionTable.generation());
return bestValue;
}
if (PvNode && bestValue > alpha)
alpha = bestValue;
futilityBase = bestValue + 128;
}
//.........这里部分代码省略.........