本文整理汇总了C#中Portfish.Position.key方法的典型用法代码示例。如果您正苦于以下问题:C# Position.key方法的具体用法?C# Position.key怎么用?C# Position.key使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Portfish.Position
的用法示例。
在下文中一共展示了Position.key方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: uci_loop
/// Wait for a command from the user, parse this text string as an UCI command,
/// and call the appropriate functions. Also intercepts EOF from stdin to ensure
/// that we exit gracefully if the GUI dies unexpectedly. In addition to the UCI
/// commands, the function also supports a few debug commands.
internal static void uci_loop(string args)
{
for (int i = 0; i < 102; i++)
{
StateRingBuf[i] = new StateInfo();
}
Position pos = new Position(StartFEN, false, Threads.main_thread()); // The root position
string cmd, token = string.Empty;
while (token != "quit")
{
if (args.Length > 0)
{
cmd = args;
}
else if (String.IsNullOrEmpty(cmd = Plug.ReadLine())) // Block here waiting for input
{
cmd = "quit";
}
Stack<string> stack = Utils.CreateStack(cmd);
token = stack.Pop();
if (token == "quit" || token == "stop")
{
Search.SignalsStop = true;
Threads.wait_for_search_finished(); // Cannot quit while threads are running
}
else if (token == "ponderhit")
{
// The opponent has played the expected move. GUI sends "ponderhit" if
// we were told to ponder on the same move the opponent has played. We
// should continue searching but switching from pondering to normal search.
Search.Limits.ponder = false;
if (Search.SignalsStopOnPonderhit)
{
Search.SignalsStop = true;
Threads.main_thread().wake_up(); // Could be sleeping
}
}
else if (token == "go")
{
go(pos, stack);
}
else if (token == "ucinewgame")
{ /* Avoid returning "Unknown command" */ }
else if (token == "isready")
{
Plug.Write("readyok");
Plug.Write(Constants.endl);
}
else if (token == "position")
{
set_position(pos, stack);
}
else if (token == "setoption")
{
set_option(stack);
}
else if (token == "validmoves")
{
Search.validmoves(pos, stack);
}
else if (token == "d")
{
pos.print(0);
}
else if (token == "flip")
{
pos.flip();
}
else if (token == "eval")
{
Plug.Write(Evaluate.trace(pos));
Plug.Write(Constants.endl);
}
else if (token == "bench")
{
Benchmark.benchmark(pos, stack);
}
else if (token == "key")
{
Plug.Write("key: ");
Plug.Write(String.Format("{0:X}", pos.key()));
Plug.Write("\nmaterial key: ");
Plug.Write(pos.material_key().ToString());
Plug.Write("\npawn key: ");
Plug.Write(pos.pawn_key().ToString());
Plug.Write(Constants.endl);
}
else if (token == "uci")
{
Plug.Write("id name "); Plug.Write(Utils.engine_info(true));
Plug.Write("\n"); Plug.Write(OptionMap.Instance.ToString());
//.........这里部分代码省略.........
示例2: search
//.........这里部分代码省略.........
// Enforce node limit here. FIXME: This only works with 1 search thread.
if ((Limits.nodes != 0) && pos.nodes >= Limits.nodes)
SignalsStop = true;
if ((SignalsStop
|| pos.is_draw(false)
|| ss[ssPos].ply > Constants.MAX_PLY) && !RootNode)
{
MovesSearchedBroker.Free();
return ValueC.VALUE_DRAW;
}
// Step 3. Mate distance pruning. Even if we mate at the next move our score
// would be at best mate_in(ss[ssPos].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
// further, we will never beat 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.
if (!RootNode)
{
alpha = Math.Max(Utils.mated_in(ss[ssPos].ply), alpha);
beta = Math.Min(Utils.mate_in(ss[ssPos].ply + 1), beta);
if (alpha >= beta)
{
MovesSearchedBroker.Free();
return alpha;
}
}
// 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 = ss[ssPos].excludedMove;
posKey = (excludedMove != 0) ? pos.exclusion_key() : pos.key();
tteHasValue = TT.probe(posKey, ref ttePos, out tte);
ttMove = RootNode ? RootMoves[PVIdx].pv[0] : tteHasValue ? tte.move() : MoveC.MOVE_NONE;
ttValue = tteHasValue ? value_from_tt(tte.value(), ss[ssPos].ply) : ValueC.VALUE_ZERO;
// At PV nodes we check for exact scores, while at non-PV nodes we check for
// a fail high/low. Biggest advantage at probing at PV nodes is to have a
// smooth experience in analysis mode. We don't probe at Root nodes otherwise
// we should also update RootMoveList to avoid bogus output.
if (!RootNode && tteHasValue && (PvNode ? tte.depth() >= depth && tte.type() == Bound.BOUND_EXACT
: can_return_tt(tte, depth, ttValue, beta)))
{
TT.entries[ttePos].set_generation(TT.generation);
ss[ssPos].currentMove = ttMove; // Can be MOVE_NONE
if (ttValue >= beta
&& (ttMove != 0)
&& !pos.is_capture_or_promotion(ttMove)
&& ttMove != ss[ssPos].killers0)
{
ss[ssPos].killers1 = ss[ssPos].killers0;
ss[ssPos].killers0 = ttMove;
}
MovesSearchedBroker.Free();
return ttValue;
}
// Step 5. Evaluate the position statically and update parent's gain statistics
if (inCheck)
ss[ssPos].eval = ss[ssPos].evalMargin = ValueC.VALUE_NONE;
else if (tteHasValue)
{
示例3: extract_pv_from_tt
/// RootMove::extract_pv_from_tt() builds a PV by adding moves from the TT table.
/// We consider also failing high nodes and not only BOUND_EXACT nodes so to
/// allow to always have a ponder move even when we fail high at root, and a
/// long PV to print that is important for position analysis.
internal void extract_pv_from_tt(Position pos)
{
StateInfoArray sia = StateInfoArrayBroker.GetObject();
int stPos = 0;
TTEntry tte;
int ply = 1;
Move m = pv[0];
Debug.Assert(m != MoveC.MOVE_NONE && pos.is_pseudo_legal(m));
pv.Clear();
pv.Add(m);
pos.do_move(m, sia.state[stPos++]);
UInt32 ttePos = 0;
while (TT.probe(pos.key(), ref ttePos, out tte)
&& (m = tte.move()) != MoveC.MOVE_NONE // Local copy, TT entry could change
&& pos.is_pseudo_legal(m)
&& pos.pl_move_is_legal(m, pos.pinned_pieces())
&& ply < Constants.MAX_PLY
&& (!pos.is_draw(false) || ply < 2))
{
pv.Add(m);
pos.do_move(m, sia.state[stPos++]);
ply++;
}
pv.Add(MoveC.MOVE_NONE);
do pos.undo_move(pv[--ply]); while (ply != 0);
StateInfoArrayBroker.Free();
}
示例4: insert_pv_in_tt
// 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)
{
StateInfoArray sia = StateInfoArrayBroker.GetObject();
int stPos = 0;
TTEntry tte;
bool tteHasValue;
Key k;
Value v, m = ValueC.VALUE_NONE;
int ply = 0;
UInt32 ttePos = 0;
Debug.Assert(pv[ply] != MoveC.MOVE_NONE && pos.is_pseudo_legal(pv[ply]));
do
{
k = pos.key();
tteHasValue = TT.probe(k, ref ttePos, out tte);
// Don't overwrite existing correct entries
if ((!tteHasValue) || tte.move() != pv[ply])
{
v = (pos.in_check() ? ValueC.VALUE_NONE : Evaluate.do_evaluate(false, pos, ref m));
TT.store(k, ValueC.VALUE_NONE, Bound.BOUND_NONE, DepthC.DEPTH_NONE, pv[ply], v, m);
}
pos.do_move(pv[ply], sia.state[stPos++]);
} while (pv[++ply] != MoveC.MOVE_NONE);
do pos.undo_move(pv[--ply]); while (ply != 0);
StateInfoArrayBroker.Free();
}
示例5: qsearch
// qsearch() is the quiescence search function, which is called by the main
// search function when the remaining depth is zero (or, to be more precise,
// less than ONE_PLY).
static Value qsearch(NodeType NT, Position pos, Stack[] ss, int ssPos, Value alpha, Value beta, Depth depth)
{
bool PvNode = (NT == NodeTypeC.PV);
Debug.Assert(NT == NodeTypeC.PV || NT == NodeTypeC.NonPV);
Debug.Assert(alpha >= -ValueC.VALUE_INFINITE && alpha < beta && beta <= ValueC.VALUE_INFINITE);
Debug.Assert((alpha == beta - 1) || PvNode);
Debug.Assert(depth <= DepthC.DEPTH_ZERO);
StateInfo st = null;
Move ttMove, move, bestMove;
Value ttValue, bestValue, value, evalMargin = 0, futilityValue, futilityBase;
bool inCheck, enoughMaterial, givesCheck, evasionPrunable;
bool tteHasValue = false;
TTEntry tte;
UInt32 ttePos = 0;
Depth ttDepth;
Bound bt;
Value oldAlpha = alpha;
ss[ssPos].currentMove = bestMove = MoveC.MOVE_NONE;
ss[ssPos].ply = ss[ssPos - 1].ply + 1;
// Check for an instant draw or maximum ply reached
if (pos.is_draw(true) || ss[ssPos].ply > Constants.MAX_PLY)
return ValueC.VALUE_DRAW;
// 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.
inCheck = pos.st.checkersBB != 0;
ttDepth = (inCheck || depth >= DepthC.DEPTH_QS_CHECKS ? DepthC.DEPTH_QS_CHECKS : DepthC.DEPTH_QS_NO_CHECKS);
// Transposition table lookup. At PV nodes, we don't use the TT for
// pruning, but only for move ordering.
tteHasValue = TT.probe(pos.key(), ref ttePos, out tte);
ttMove = (tteHasValue ? tte.move() : MoveC.MOVE_NONE);
ttValue = tteHasValue ? value_from_tt(tte.value(), ss[ssPos].ply) : ValueC.VALUE_ZERO;
if (!PvNode && tteHasValue && can_return_tt(tte, ttDepth, ttValue, beta))
{
ss[ssPos].currentMove = ttMove; // Can be MOVE_NONE
return ttValue;
}
// Evaluate the position statically
if (inCheck)
{
bestValue = futilityBase = -ValueC.VALUE_INFINITE;
ss[ssPos].eval = evalMargin = ValueC.VALUE_NONE;
enoughMaterial = false;
}
else
{
if (tteHasValue)
{
Debug.Assert(tte.static_value() != ValueC.VALUE_NONE);
evalMargin = tte.static_value_margin();
ss[ssPos].eval = bestValue = tte.static_value();
}
else
ss[ssPos].eval = bestValue = Evaluate.do_evaluate(false, pos, ref evalMargin);
// Stand pat. Return immediately if static value is at least beta
if (bestValue >= beta)
{
if (!tteHasValue)
TT.store(pos.key(), value_to_tt(bestValue, ss[ssPos].ply), Bound.BOUND_LOWER, DepthC.DEPTH_NONE, MoveC.MOVE_NONE, ss[ssPos].eval, evalMargin);
return bestValue;
}
if (PvNode && bestValue > alpha)
alpha = bestValue;
futilityBase = ss[ssPos].eval + evalMargin + FutilityMarginQS;
enoughMaterial = (pos.sideToMove == 0 ? pos.st.npMaterialWHITE : pos.st.npMaterialBLACK) > Constants.RookValueMidgame;
}
// Initialize a MovePicker object for the current position, and prepare
// to search the moves. Because the depth is <= 0 here, only captures,
// queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will
// be generated.
MovePicker mp = MovePickerBroker.GetObject();
mp.MovePickerC(pos, ttMove, depth, H, (ss[ssPos - 1].currentMove) & 0x3F);
CheckInfo ci = CheckInfoBroker.GetObject();
ci.CreateCheckInfo(pos);
// Loop through the moves until no moves remain or a beta cutoff occurs
while (bestValue < beta
&& (move = mp.next_move()) != MoveC.MOVE_NONE)
{
Debug.Assert(Utils.is_ok_M(move));
givesCheck = pos.move_gives_check(move, ci);
//.........这里部分代码省略.........
示例6: 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, 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.
internal static int search(int NT, Position pos, Stack[] ss, int ssPos, int alpha, int beta, int depth)
{
var PvNode = (NT == NodeTypeC.PV || NT == NodeTypeC.Root || NT == NodeTypeC.SplitPointPV
|| NT == NodeTypeC.SplitPointRoot);
var SpNode = (NT == NodeTypeC.SplitPointPV || NT == NodeTypeC.SplitPointNonPV
|| NT == NodeTypeC.SplitPointRoot);
var RootNode = (NT == NodeTypeC.Root || NT == NodeTypeC.SplitPointRoot);
Debug.Assert(alpha >= -ValueC.VALUE_INFINITE && alpha < beta && beta <= ValueC.VALUE_INFINITE);
Debug.Assert((PvNode || alpha == beta - 1));
Debug.Assert(depth > DepthC.DEPTH_ZERO);
var ms = MovesSearchedBroker.GetObject();
var movesSearched = ms.movesSearched;
StateInfo st = null;
var tte = TT.StaticEntry;
var tteHasValue = false;
uint ttePos = 0;
ulong posKey = 0;
int ttMove, move, excludedMove, bestMove, threatMove;
int ext, newDepth;
int bestValue, value, ttValue;
int eval = 0, nullValue, futilityValue;
bool inCheck, givesCheck, pvMove, singularExtensionNode;
bool captureOrPromotion, dangerous, doFullDepthSearch;
int moveCount = 0, playedMoveCount = 0;
SplitPoint sp = null;
// Step 1. Initialize node
var thisThread = pos.this_thread();
//var threatExtension = false;
inCheck = pos.in_check();
if (SpNode)
{
sp = ss[ssPos].sp;
bestMove = sp.bestMove;
threatMove = sp.threatMove;
bestValue = sp.bestValue;
ttMove = excludedMove = MoveC.MOVE_NONE;
ttValue = ValueC.VALUE_NONE;
Debug.Assert(sp.bestValue > -ValueC.VALUE_INFINITE && sp.moveCount > 0);
goto split_point_start;
}
bestValue = -ValueC.VALUE_INFINITE;
ss[ssPos].currentMove = threatMove = ss[ssPos + 1].excludedMove = bestMove = MoveC.MOVE_NONE;
ss[ssPos].ply = ss[ssPos - 1].ply + 1;
ss[ssPos + 1].skipNullMove = 0;
ss[ssPos + 1].reduction = DepthC.DEPTH_ZERO;
ss[ssPos + 2].killers0 = ss[ssPos + 2].killers1 = MoveC.MOVE_NONE;
// Used to send selDepth info to GUI
if (PvNode && thisThread.maxPly < ss[ssPos].ply)
{
thisThread.maxPly = ss[ssPos].ply;
}
if (!RootNode)
{
// Step 2. Check for aborted search and immediate draw
if ((SignalsStop || pos.is_draw(false) || ss[ssPos].ply > Constants.MAX_PLY))
{
MovesSearchedBroker.Free();
return DrawValue[pos.sideToMove];
}
// 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
// further, we will never beat 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 = Math.Max(Utils.mated_in(ss[ssPos].ply), alpha);
beta = Math.Min(Utils.mate_in(ss[ssPos].ply + 1), beta);
if (alpha >= beta)
{
MovesSearchedBroker.Free();
return alpha;
}
}
// 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 = ss[ssPos].excludedMove;
posKey = (excludedMove != 0) ? pos.exclusion_key() : pos.key();
tteHasValue = TT.probe(posKey, ref ttePos, out tte);
ttMove = RootNode ? RootMoves[PVIdx].pv[0] : tteHasValue ? tte.move() : MoveC.MOVE_NONE;
ttValue = tteHasValue ? value_from_tt(tte.value(), ss[ssPos].ply) : ValueC.VALUE_NONE;
//.........这里部分代码省略.........
示例7: qsearch
// qsearch() is the quiescence search function, which is called by the main
// search function when the remaining depth is zero (or, to be more precise,
// less than ONE_PLY).
private static int qsearch(int NT, bool InCheck, Position pos, Stack[] ss, int ssPos, int alpha, int beta, int depth)
{
var PvNode = (NT == NodeTypeC.PV);
Debug.Assert(NT == NodeTypeC.PV || NT == NodeTypeC.NonPV);
Debug.Assert(InCheck == pos.in_check());
Debug.Assert(alpha >= -ValueC.VALUE_INFINITE && alpha < beta && beta <= ValueC.VALUE_INFINITE);
Debug.Assert(PvNode || (alpha == beta - 1));
Debug.Assert(depth <= DepthC.DEPTH_ZERO);
StateInfo st = null;
int ttMove, move, bestMove;
int ttValue, bestValue, value, futilityValue, futilityBase, oldAlpha = 0;
bool givesCheck, enoughMaterial, evasionPrunable, fromNull;
var tteHasValue = false;
TTEntry tte;
uint ttePos = 0;
int ttDepth;
Key posKey;
// To flag BOUND_EXACT a node with eval above alpha and no available moves
if (PvNode)
{
oldAlpha = alpha;
}
ss[ssPos].currentMove = bestMove = MoveC.MOVE_NONE;
ss[ssPos].ply = ss[ssPos - 1].ply + 1;
fromNull = ss[ssPos - 1].currentMove == MoveC.MOVE_NULL;
// Check for an instant draw or maximum ply reached
if (pos.is_draw(true) || ss[ssPos].ply > Constants.MAX_PLY)
{
return DrawValue[pos.sideToMove];
}
// Transposition table lookup. At PV nodes, we don't use the TT for
// pruning, but only for move ordering.
posKey = pos.key();
tteHasValue = TT.probe(posKey, ref ttePos, out tte);
ttMove = (tteHasValue ? tte.move() : MoveC.MOVE_NONE);
ttValue = tteHasValue ? value_from_tt(tte.value(), ss[ssPos].ply) : ValueC.VALUE_NONE;
// 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.
ttDepth = (InCheck || depth >= DepthC.DEPTH_QS_CHECKS ? DepthC.DEPTH_QS_CHECKS : DepthC.DEPTH_QS_NO_CHECKS);
if (tteHasValue
&& tte.depth() >= depth
&& ttValue != ValueC.VALUE_NONE // Only in case of TT access race
&& (PvNode ? tte.type() == Bound.BOUND_EXACT
: ttValue >= beta ? ((tte.type() & Bound.BOUND_LOWER) != 0)
: ((tte.type() & Bound.BOUND_UPPER) != 0)))
{
ss[ssPos].currentMove = ttMove; // Can be MOVE_NONE
return ttValue;
}
// Evaluate the position statically
if (InCheck)
{
ss[ssPos].staticEval = ss[ssPos].evalMargin = ValueC.VALUE_NONE;
bestValue = futilityBase = -ValueC.VALUE_INFINITE;
enoughMaterial = false;
}
else
{
if (fromNull)
{
// Approximated score. Real one is slightly higher due to tempo
ss[ssPos].staticEval = bestValue = -ss[ssPos - 1].staticEval;
ss[ssPos].evalMargin = ValueC.VALUE_ZERO;
}
else if (tteHasValue)
{
// Never assume anything on values stored in TT
if ((ss[ssPos].staticEval = bestValue = tte.eval_value()) == ValueC.VALUE_NONE
|| (ss[ssPos].evalMargin = tte.eval_margin()) == ValueC.VALUE_NONE)
{
ss[ssPos].staticEval = bestValue = Evaluate.do_evaluate(false, pos, ref ss[ssPos].evalMargin);
}
}
else
{
ss[ssPos].staticEval = bestValue = Evaluate.do_evaluate(false, pos, ref ss[ssPos].evalMargin);
}
// Stand pat. Return immediately if static value is at least beta
if (bestValue >= beta)
{
if (!tteHasValue)
{
TT.store(
pos.key(),
value_to_tt(bestValue, ss[ssPos].ply),
//.........这里部分代码省略.........
示例8: insert_pv_in_tt
// 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 sia = StateInfoArrayBroker.GetObject();
var stPos = 0;
TTEntry tte;
bool tteHasValue;
int v, m = 0;
var ply = 0;
uint ttePos = 0;
do
{
tteHasValue = TT.probe(pos.key(), ref ttePos, out tte);
if ((!tteHasValue) || tte.move() != this.pv[ply]) // Don't overwrite existing correct entries
{
if (pos.in_check())
{
v = m = ValueC.VALUE_NONE;
}
else
{
v = Evaluate.do_evaluate(false, pos, ref m);
}
TT.store(pos.key(), ValueC.VALUE_NONE, Bound.BOUND_NONE, DepthC.DEPTH_NONE, this.pv[ply], v, m);
}
Debug.Assert(pos.move_is_legal(pv[ply]));
pos.do_move(this.pv[ply++], sia.state[stPos++]);
}
while (this.pv[ply] != MoveC.MOVE_NONE);
while (ply != 0)
{
pos.undo_move(this.pv[--ply]);
}
StateInfoArrayBroker.Free();
}
示例9: extract_pv_from_tt
/// RootMove::extract_pv_from_tt() builds a PV by adding moves from the TT table.
/// We consider also failing high nodes and not only BOUND_EXACT nodes so to
/// allow to always have a ponder move even when we fail high at root, and a
/// long PV to print that is important for position analysis.
internal void extract_pv_from_tt(Position pos)
{
var sia = StateInfoArrayBroker.GetObject();
var stPos = 0;
TTEntry tte;
bool tteHasValue;
var ply = 0;
var m = this.pv[0];
this.pv.Clear();
uint ttePos = 0;
do
{
this.pv.Add(m);
Debug.Assert(pos.move_is_legal(pv[ply]));
pos.do_move(pv[ply++], sia.state[stPos++]);
tteHasValue = TT.probe(pos.key(), ref ttePos, out tte);
} while (tteHasValue
&& pos.is_pseudo_legal(m = tte.move()) // Local copy, TT could change
&& pos.pl_move_is_legal(m, pos.pinned_pieces())
&& ply < Constants.MAX_PLY
&& (!pos.is_draw(false) || ply < 2));
;
this.pv.Add(MoveC.MOVE_NONE); // Must be zero-terminating
while (ply != 0)
{
pos.undo_move(this.pv[--ply]);
}
StateInfoArrayBroker.Free();
}
示例10: loop
/// Wait for a command from the user, parse this text string as an UCI command,
/// and call the appropriate functions. Also intercepts EOF from stdin to ensure
/// that we exit gracefully if the GUI dies unexpectedly. In addition to the UCI
/// commands, the function also supports a few debug commands.
internal static void loop(string args)
{
for (var i = 0; i < 102; i++)
{
StateRingBuf[i] = new StateInfo();
}
var pos = new Position(StartFEN, false, Threads.main_thread()); // The root position
string cmd, token = string.Empty;
while (token != "quit")
{
if (args.Length > 0)
{
cmd = args;
}
else if (string.IsNullOrEmpty(cmd = Plug.ReadLine())) // Block here waiting for input
{
cmd = "quit";
}
var stack = Utils.CreateStack(cmd);
token = stack.Pop();
if (token == "quit" || token == "stop" || token == "ponderhit")
{
// GUI sends 'ponderhit' to tell us to ponder on the same move the
// opponent has played. In case Signals.stopOnPonderhit is set we are
// waiting for 'ponderhit' to stop the search (for instance because we
// already ran out of time), otherwise we should continue searching but
// switching from pondering to normal search.
if (token != "ponderhit" || Search.SignalsStopOnPonderhit)
{
Search.SignalsStop = true;
Threads.main_thread().notify_one(); // Could be sleeping
}
else
{
Search.Limits.ponder = false;
}
}
else if (token == "go")
{
go(pos, stack);
}
else if (token == "ucinewgame")
{
TT.clear();
}
else if (token == "isready")
{
Plug.Write("readyok");
Plug.Write(Constants.endl);
}
else if (token == "position")
{
set_position(pos, stack);
}
else if (token == "setoption")
{
set_option(stack);
}
else if (token == "validmoves")
{
Search.validmoves(pos, stack);
}
else if (token == "d")
{
pos.print(0);
}
else if (token == "flip")
{
pos.flip();
}
else if (token == "eval")
{
Plug.Write(Evaluate.trace(pos));
Plug.Write(Constants.endl);
}
else if (token == "bench")
{
Benchmark.benchmark(pos, stack);
}
else if (token == "key")
{
Plug.Write("key: ");
Plug.Write(string.Format("{0:X}", pos.key()));
Plug.Write("\nmaterial key: ");
Plug.Write(pos.material_key().ToString());
Plug.Write("\npawn key: ");
Plug.Write(pos.pawn_key().ToString());
Plug.Write(Constants.endl);
}
else if (token == "uci")
{
//.........这里部分代码省略.........