public void Start(NagNode nagNode, int boardSize) { BoardSize = boardSize; NagNode = nagNode; NagNode.Worker = this; Start(nagNode.PlayerToMove, nagNode.MoveList, nagNode.Depth, nagNode.Alpha, nagNode.Beta, nagNode.PermutationNbr); }
public void NewNagPoint(NagNode nagNode) { lock (this) { AvailableNagNodes.Add(nagNode); } InstructWorkers(); }
public void Disconnect() { lock (this) { Console.Error.WriteLine("STATUS: Disconnecting Connection"); State = ConnectionState.Disconnecting; NagNode = null; NagCoordinator.Disconnected(this); Worker.Disconnect(true); } }
public NagNode(NagNode nagNode, int permutationNbr) { MoveList = nagNode.MoveList; Alpha = nagNode.Alpha; Beta = nagNode.Beta; PlayerToMove = nagNode.PlayerToMove; Depth = nagNode.Depth; ZobristHash = nagNode.ZobristHash; NarrowedAlpha = nagNode.NarrowedAlpha; NarrowedBeta = nagNode.NarrowedBeta; StartDepth = nagNode.StartDepth; PermutationNbr = permutationNbr; }
protected bool IsStillValid(NagNode lNagNode) { lock (this) { List <NagNode> lNagNodes = NagNodeByDepth[lNagNode.StartDepth]; if (lNagNodes == null) { return(false); } return(lNagNodes.Contains(lNagNode)); } }
public void WorkerResult(NagNode nagNode) { lock (this) { // note: unless nag results might be put on this list // so the results need to be rechecked later Results.Add(nagNode); } if (OnNag != null) { OnNag(); // tell search that results are available } }
public void Abort() { lock (this) { if (State == ConnectionState.Ready) { return; } if (State != ConnectionState.Thinking) { return; } State = ConnectionState.Aborting; NagNode = null; SendCommand("abort", FormatIdNbr(++CommandNbr, 1)); } }
public void Initalize(int boardSize) { lock (this) { if (State == ConnectionState.Thinking) { Abort(); return; } if (!((State == ConnectionState.Available) || (State == ConnectionState.Ready))) { return; } NagNode = null; State = ConnectionState.Initializing; CommandNbr++; SendCommand("set_boardsize", FormatIdNbr(CommandNbr, 1), boardSize); } }
public void CreateNagPoints(GoBoard goBoard, int alpha, int beta, Color playerToMove, int depth, int maxDepth, int moves, int maxNags) { int lLevels = maxDepth - depth; if (lLevels < 3) // avoid shallow searches { return; } int lAvailableWorkersCount = AvailableWorkersCount; if (lAvailableWorkersCount == 0) { return; } List <NagNode> lNagNodes = null; lock (this) { lNagNodes = new List <NagNode>(); NagNode lNagNode = new NagNode(goBoard, alpha, beta, playerToMove, depth, maxDepth - depth, Random.Next(9) + 1); lNagNodes.Add(lNagNode); int lNew = Math.Min(Math.Min(lAvailableWorkersCount - 1, moves), maxNags - 1); for (int i = 0; i < lNew; i++) { NagNode lNagNode2 = new NagNode(lNagNode, Random.Next(9) + 1); lNagNodes.Add(lNagNode2); } NagNodeByDepth[depth] = lNagNodes; } NewNagPoints(lNagNodes); }
protected void InstructWorkersThread() { lock (this) { while (AvailableWorkers.Count != 0) { if (AvailableNagNodes.Count == 0) { return; } int lIndex = Random.Next(AvailableNagNodes.Count); WorkerProxy lWorkerProxy = AvailableWorkers[0]; NagNode lNagNode = AvailableNagNodes[lIndex]; AvailableWorkers.RemoveAt(0); AvailableNagNodes.RemoveAt(lIndex); lWorkerProxy.Start(lNagNode, BoardSize); } } }
public int Search(Color playerToMove, int maxPly, int depth, int alpha, int beta) { ZobristHash lZobristHash = Board.ZobristHash.Clone(); lZobristHash.Mark(playerToMove); int lTryMove = CoordinateSystem.PASS; if (depth > 1) { TranspositionTablePlus.Node lNode = TranspositionTable.Retrieve(lZobristHash); if ((lNode.Flag != TranspositionTablePlus.NodeType.Unknown) && (lNode.Height > 0)) { if ((maxPly - depth) <= lNode.Height) { TranspositionTableHits++; switch (lNode.Flag) { case TranspositionTablePlus.NodeType.Exact: { SearchComplete = false; return(lNode.Value); } case TranspositionTablePlus.NodeType.LowerBound: { alpha = (alpha > lNode.Value) ? alpha : lNode.Value; break; } case TranspositionTablePlus.NodeType.UpperBound: { beta = (beta < lNode.Value) ? beta : lNode.Value; break; } } if (alpha >= beta) { return(lNode.Value); } } lTryMove = lNode.Move; } } if ((depth == maxPly) || ((depth != 0) && (SearchInterface.IsGameOver()))) { if (depth == maxPly) { SearchComplete = false; } NodesEvaluated++; int lEval = SearchInterface.Evaluate(playerToMove); if (lEval <= alpha) { TranspositionTable.Record(maxPly - depth, lEval, TranspositionTablePlus.NodeType.LowerBound, CoordinateSystem.PASS, lZobristHash); } else if (lEval >= beta) { TranspositionTable.Record(maxPly - depth, lEval, TranspositionTablePlus.NodeType.UpperBound, CoordinateSystem.PASS, lZobristHash); } else { TranspositionTable.Record(maxPly - depth, lEval, TranspositionTablePlus.NodeType.Exact, CoordinateSystem.PASS, lZobristHash); } return(lEval); } MoveList lMoves = SearchInterface.GetMoveList(playerToMove, SearchOptions.IncludeEndGameMoves); SearchInterface.PruneMoveList(lMoves); SearchInterface.PrioritizeMoves(lMoves, playerToMove); if (lTryMove != CoordinateSystem.PASS) { if (lMoves.Contains(lTryMove)) { lMoves.SetValue(lTryMove, Int32.MaxValue); } } if ((SearchOptions.UsePatterns) && (lMoves.Count != 0)) { PatternMap lPatternMap = SearchOptions.PatternDetector.FindPatterns(Board, playerToMove, lMoves.AllMoves); lPatternMap.UpdateMoveList(lMoves); } if (lMoves.Count == 0) { lMoves.Add(CoordinateSystem.PASS); } if ((lMoves.Count == 1) && (lMoves[0] == CoordinateSystem.PASS) && (Board.LastMove == CoordinateSystem.PASS)) { int lEval = SearchInterface.Evaluate(playerToMove); //TranspositionTable.Record(maxPly - depth, lEval, TranspositionTablePlus.NodeType.Exact, CoordinateSystem.PASS, lZobristHash); return(lEval); } if (Nag) { lock (this) { NagNode lNagNode = NagCoordinator.GetResult(depth); if (lNagNode != null) { if (!lNagNode.IsNarrowed()) { Console.Error.WriteLine("*** Pruning *** " + lNagNode.StartDepth.ToString() + "/" + lNagNode.Depth.ToString()); if (lNagNode.Depth == 1) { BestMove = lNagNode.BestMove; NagCoordinator.Abort(depth); return(lNagNode.Result); } SolvedDepth = lNagNode.StartDepth; SolvedValue = lNagNode.Result; NagCoordinator.Abort(depth); return(alpha); } } else { Nag = false; } } } SearchInterface.SortMoveList(lMoves); if (UpdateStatusFlag) { UpdateStatus(); } if (StopThinkingFlag) { Stop(); } NagCoordinator.CreateNagPoints(Board, alpha, beta, playerToMove, depth, maxPly, lMoves.Count, 2); int lSuperKoCount = 0; TranspositionTablePlus.NodeType lFlag = TranspositionTablePlus.NodeType.UpperBound; int lBestMove = lMoves[0]; foreach (int lMove in lMoves) { NodesSearched++; bool lPlayed = Board.PlayStone(lMove, playerToMove, true); if (!lPlayed) { throw new ApplicationException("SearchMethodAB_ID_TT.cs: You hit a bug!"); } if ((CheckSuperKo) && (Board.IsSuperKo())) { lSuperKoCount++; Board.Undo(); } else { int lScore = -Search(playerToMove.Opposite, maxPly, depth + 1, -beta, -alpha); Board.Undo(); if (SolvedDepth != -1) { if (SolvedDepth != depth) { return(alpha); } alpha = SolvedValue; BestMove = lMove; SolvedDepth = -1; break; } if (lScore > alpha) { if (depth == 0) { BestMove = lMove; } if (lScore >= beta) { TranspositionTable.Record(maxPly - depth, alpha, TranspositionTablePlus.NodeType.LowerBound, lMove, lZobristHash); NagCoordinator.Abort(depth); return(beta); } alpha = lScore; lFlag = TranspositionTablePlus.NodeType.Exact; lBestMove = lMove; } } } if (lSuperKoCount == lMoves.Count) { NagCoordinator.Abort(depth); return(SearchInterface.Evaluate(playerToMove)); } TranspositionTable.Record(maxPly - depth, alpha, lFlag, lBestMove, lZobristHash); NagCoordinator.Abort(depth); return(alpha); }
public void Abort() { lock (this) { if (State == ConnectionState.Ready) return; if (State != ConnectionState.Thinking) return; State = ConnectionState.Aborting; NagNode = null; SendCommand("abort", FormatIdNbr(++CommandNbr, 1)); } }
public void ProcesLine(string line) { if (line == null) { Disconnect(); return; } string lLine = line.TrimEnd('\n'); string[] lCmds = lLine.Split('\t'); bool lAsync = (lCmds[0][0] == '!'); bool lSuccess = (lCmds[0][lAsync ? 1 : 0] == '='); string[] lID = lCmds[1].Split('.'); int lCommandNbr = Convert.ToInt32(lID[0]); int lSeqNbr = Convert.ToInt32(lID[1]); if ((Verbose) && (lCmds.Length > 3)) Console.Error.WriteLine("STATUS: P< " + lLine); lock (this) { if ((lCommandNbr == 0) && (lSeqNbr == 0) && (!lSuccess)) { // worker disconnecting... Disconnect(); return; } if (State == ConnectionState.Negotiating) { if ((!lSuccess) || (lCmds[2] != "1.0")) { Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Negotiated; ThreadPoolHelperWithParam<WorkerProxy>.Execute(NagCoordinator.WorkerNegotiated, this); //NagCoordinator.WorkerNegotiated(this); } } else if (State == ConnectionState.SendingPatterns) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Available; ThreadPoolHelperWithParam<WorkerProxy>.Execute(NagCoordinator.WorkerAvailable, this); //NagCoordinator.WorkerAvailable(this); } } } else if (State == ConnectionState.Initializing) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { // error with commands, disconnect to reset worker Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Ready; ThreadPoolHelperWithParam<WorkerProxy>.Execute(NagCoordinator.WorkerReady, this); // NagCoordinator.WorkerReady(this); } } } else if (State == ConnectionState.Thinking) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { // error with commands, disconnect to reset worker Disconnect(); return; } if ((lSeqNbr == 6) && (lAsync)) { State = ConnectionState.Ready; if (NagNode != null) { NagNode.SetResult(Convert.ToInt32(lCmds[3]), CoordinateSystem.At(lCmds[2], BoardSize)); ThreadPoolHelperWithParam<NagNode>.Execute(NagCoordinator.WorkerResult, NagNode); NagNode = null; } ThreadPoolHelperWithParam<WorkerProxy>.Execute(NagCoordinator.WorkerReady, this); } } } else if (State == ConnectionState.Aborting) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { // error with commands, disconnect to reset worker Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Ready; NagNode = null; ThreadPoolHelperWithParam<WorkerProxy>.Execute(NagCoordinator.WorkerReady, this); } } } } }
public void Initalize(int boardSize) { lock (this) { if (State == ConnectionState.Thinking) { Abort(); return; } if (!((State == ConnectionState.Available) || (State == ConnectionState.Ready))) return; NagNode = null; State = ConnectionState.Initializing; CommandNbr++; SendCommand("set_boardsize", FormatIdNbr(CommandNbr, 1), boardSize); } }
public void ProcesLine(string line) { if (line == null) { Disconnect(); return; } string lLine = line.TrimEnd('\n'); string[] lCmds = lLine.Split('\t'); bool lAsync = (lCmds[0][0] == '!'); bool lSuccess = (lCmds[0][lAsync ? 1 : 0] == '='); string[] lID = lCmds[1].Split('.'); int lCommandNbr = Convert.ToInt32(lID[0]); int lSeqNbr = Convert.ToInt32(lID[1]); if ((Verbose) && (lCmds.Length > 3)) { Console.Error.WriteLine("STATUS: P< " + lLine); } lock (this) { if ((lCommandNbr == 0) && (lSeqNbr == 0) && (!lSuccess)) { // worker disconnecting... Disconnect(); return; } if (State == ConnectionState.Negotiating) { if ((!lSuccess) || (lCmds[2] != "1.0")) { Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Negotiated; ThreadPoolHelperWithParam <WorkerProxy> .Execute(NagCoordinator.WorkerNegotiated, this); //NagCoordinator.WorkerNegotiated(this); } } else if (State == ConnectionState.SendingPatterns) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Available; ThreadPoolHelperWithParam <WorkerProxy> .Execute(NagCoordinator.WorkerAvailable, this); //NagCoordinator.WorkerAvailable(this); } } } else if (State == ConnectionState.Initializing) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { // error with commands, disconnect to reset worker Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Ready; ThreadPoolHelperWithParam <WorkerProxy> .Execute(NagCoordinator.WorkerReady, this); // NagCoordinator.WorkerReady(this); } } } else if (State == ConnectionState.Thinking) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { // error with commands, disconnect to reset worker Disconnect(); return; } if ((lSeqNbr == 6) && (lAsync)) { State = ConnectionState.Ready; if (NagNode != null) { NagNode.SetResult(Convert.ToInt32(lCmds[3]), CoordinateSystem.At(lCmds[2], BoardSize)); ThreadPoolHelperWithParam <NagNode> .Execute(NagCoordinator.WorkerResult, NagNode); NagNode = null; } ThreadPoolHelperWithParam <WorkerProxy> .Execute(NagCoordinator.WorkerReady, this); } } } else if (State == ConnectionState.Aborting) { if (CommandNbr == lCommandNbr) { if (!lSuccess) { // error with commands, disconnect to reset worker Disconnect(); return; } if (lSeqNbr == 1) { State = ConnectionState.Ready; NagNode = null; ThreadPoolHelperWithParam <WorkerProxy> .Execute(NagCoordinator.WorkerReady, this); } } } } }
public void CreateNagPoints(GoBoard goBoard, int alpha, int beta, Color playerToMove, int depth, int maxDepth, int moves, int maxNags) { int lLevels = maxDepth - depth; if (lLevels < 3) // avoid shallow searches return; int lAvailableWorkersCount = AvailableWorkersCount; if (lAvailableWorkersCount == 0) return; List<NagNode> lNagNodes = null; lock (this) { lNagNodes = new List<NagNode>(); NagNode lNagNode = new NagNode(goBoard, alpha, beta, playerToMove, depth, maxDepth - depth, Random.Next(9) + 1); lNagNodes.Add(lNagNode); int lNew = Math.Min(Math.Min(lAvailableWorkersCount - 1, moves), maxNags - 1); for (int i = 0; i < lNew; i++) { NagNode lNagNode2 = new NagNode(lNagNode, Random.Next(9) + 1); lNagNodes.Add(lNagNode2); } NagNodeByDepth[depth] = lNagNodes; } NewNagPoints(lNagNodes); }
public void WorkerResult(NagNode nagNode) { lock (this) { // note: unless nag results might be put on this list // so the results need to be rechecked later Results.Add(nagNode); } if (OnNag != null) OnNag(); // tell search that results are available }
protected bool IsStillValid(NagNode lNagNode) { lock (this) { List<NagNode> lNagNodes = NagNodeByDepth[lNagNode.StartDepth]; if (lNagNodes == null) return false; return lNagNodes.Contains(lNagNode); } }