//1ターン = 深さ2 protected override void Solve() { for (int i = 0; i < 50; ++i) { dp[i].Score = int.MinValue; } int deepness = StartDepth; int maxDepth = (TurnCount - CurrentTurn) * 2; PointEvaluator.Base evaluator = (TurnCount / 3 * 2) < CurrentTurn ? PointEvaluator_Normal : PointEvaluator_Dispersion; SearchState state = new SearchState(MyBoard, EnemyBoard, new Player(MyAgent1, MyAgent2), new Player(EnemyAgent1, EnemyAgent2), WaysPool); for (; deepness <= 1; deepness++) { NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator); if (CancellationToken.IsCancellationRequested == false) { SolverResult = new Decided(dp[0].Agent1Way, dp[0].Agent2Way); } else { break; } Log("[SOLVER] deepness = {0}", deepness); } }
public void SetDecisions(int index, Decided decideds) { viewModel.Players[index].Decisions = decideds.Data; viewModel.Players[index].DecisionsSelectedIndex = 0; var decided = decideds[0]; SetDecision(index, decided); }
public void OnDecided(Decided decided) { gameManager.viewModel.MainWindowDispatcher.Invoke(() => { gameManager.SetDecisions(managerNum, decided); }); // _decided = decided[0]; //gameManager.viewModel.MainWindowDispatcher.Invoke(decidedMethod); }
void Regulus.Game.IStage.Enter() { _Timeout = new Utility.TimeCounter(); _Decideds = new List<Decided>(); foreach(var player in _Players) { var decided = new Decided() { Owner = player }; player.OnSpawnReadyCaptureEnergy(decided); _Decideds.Add(decided); } }
//Meが動くとする。「Meのスコア - Enemyのスコア」の最大値を返す。 private int NegaMax(int deepness, SearchState state, int alpha, int beta, int count, PointEvaluator.Base evaluator, Decided ngMove, int greedyDepth) { if (deepness == 0) { for (int j = 0; j < greedyDepth; j++) { Way move = state.MakeGreedyMove(ScoreBoard, WayEnumerator); state.Move(move.Agent1Way, move.Agent2Way); //Ways moves = state.MakeMoves(WayEnumerator); //SortMoves(ScoreBoard, state, moves, 49, null); //state.Move(moves[0].Agent1Way, moves[1].Agent2Way); } int score = evaluator.Calculate(ScoreBoard, state.MeBoard, 0) - evaluator.Calculate(ScoreBoard, state.EnemyBoard, 0); if (greedyDepth % 2 == 1) { return(-score); } return(score); } Ways ways = state.MakeMoves(WayEnumerator); SortMoves(ScoreBoard, state, ways, count, ngMove); for (int i = 0; i < ways.Count; i++) { if (CancellationToken.IsCancellationRequested == true) { return(alpha); } //何を返しても良いのでとにかく返す //if (count == 0 && !(ngMove is null) && new Decided(ways[i].Agent1Way, ways[i].Agent2Way).Equals(ngMove)) { continue; } //競合手を避ける場合 if (count == 0 && !(ngMove is null) && (ways[i].Agent1Way.Equals(ngMove.MeAgent1) || ways[i].Agent2Way.Equals(ngMove.MeAgent2))) { continue; } //2人とも競合手とは違う手を指す SearchState nextState = state; nextState.Move(ways[i].Agent1Way, ways[i].Agent2Way); int res = -NegaMax(deepness - 1, nextState, -beta, -alpha, count + 1, evaluator, ngMove, greedyDepth); if (alpha < res) { alpha = res; if (ngMove is null) { dp1[count].UpdateScore(alpha, ways[i].Agent1Way, ways[i].Agent2Way); } else { dp2[count].UpdateScore(alpha, ways[i].Agent1Way, ways[i].Agent2Way); } if (alpha >= beta) { return(beta); //βcut } } } ways.Erase(); WaysPool.Return(ways); return(alpha); }
protected override void EndSolve(object sender, EventArgs e) { base.EndSolve(sender, e); lastTurnDecided = SolverResultList[0]; //0番目の手を指したとする。(次善手を人間が選んで競合した~ということがなければOK) }
//1ターン = 深さ2 protected override void Solve() { for (int i = 0; i < 50; ++i) { dp1[i].Score = int.MinValue; dp2[i].Score = int.MinValue; } int deepness = StartDepth; int maxDepth = (TurnCount - CurrentTurn) * 2 + 2; PointEvaluator.Base evaluator = (TurnCount / 3 * 2) < CurrentTurn ? PointEvaluator_Normal : PointEvaluator_Dispersion; SearchState state = new SearchState(MyBoard, EnemyBoard, MyAgents, EnemyAgents); int score = PointEvaluator_Normal.Calculate(ScoreBoard, state.MeBoard, 0, state.Me, state.Enemy) - PointEvaluator_Normal.Calculate(ScoreBoard, state.EnemyBoard, 0, state.Enemy, state.Me); Log("TurnCount = {0}, CurrentTurn = {1}", TurnCount, CurrentTurn); //if (!(lastTurnDecided is null)) Log("IsAgent1Moved = {0}, IsAgent2Moved = {1}, lastTurnDecided = {2}", IsAgent1Moved, IsAgent2Moved, lastTurnDecided); if (!(lastTurnDecided is null) && score > 0) //勝っている状態で競合していたら { int i; for (i = 0; i < AgentsCount; ++i) { if (IsAgentsMoved[i]) { break; } } if (i == AgentsCount) { SolverResultList.Add(lastTurnDecided); return; } } for (; deepness <= maxDepth; deepness++) { Decided resultList = new Decided(); int greedyDepth = Math.Min(greedyMaxDepth, maxDepth - deepness); if ((deepness + greedyDepth) % 2 == 1 && greedyDepth > 0) { greedyDepth--; } //普通にNegaMaxをして、最善手を探す NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, null, greedyDepth); Decision best1 = new Decision(Unsafe8Array <VelocityPoint> .Create(dp1[0].Ways.GetEnumerable(AgentsCount).Select(x => x.Direction).ToArray())); resultList.Add(best1); //競合手.Agent1 == 最善手.Agent1 && 競合手.Agent2 == 最善手.Agent2になった場合、競合手をngMoveとして探索をおこない、最善手を探す for (int i = 0; i < AgentsCount; ++i) { if (IsAgentsMoved[i] || !lastTurnDecided.Agents[i].Equals(best1.Agents[i])) { break; } if (i < AgentsCount - 1) { continue; } NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, best1, greedyDepth); Decision best2 = new Decision(Unsafe8Array <VelocityPoint> .Create(dp2[0].Ways.GetEnumerable(AgentsCount).Select(x => x.Direction).ToArray())); resultList.Add(best2); } if (CancellationToken.IsCancellationRequested == false) { SolverResultList = resultList; if (SolverResultList.Count == 2 && score <= 0) //現時点で引き分けか負けていたら競合を避けるのを優先してみる(デバッグ用) { var tmp = SolverResultList[0]; SolverResultList[0] = SolverResultList[1]; SolverResultList[1] = tmp; Log("[SOLVER] Swaped! {0} {1}", SolverResult.Agents[0], SolverResult.Agents[1]); } Log("[SOLVER] SolverResultList.Count = {0}, score = {1}", SolverResultList.Count, score); } else { return; } Log("[SOLVER] deepness = {0}", deepness); } }
public void OnDecided(Decided decided) { gameManager.ClearDecisions(managerNum); _decided = decided; gameManager.viewModel.MainWindowDispatcher.Invoke(decidedMethod); }
//1ターン = 深さ2 protected override void Solve() { int i; for (i = 0; i < 50; ++i) { dp[i].Score = int.MinValue; } int deepness = StartDepth; int maxDepth = (TurnCount - CurrentTurn) * 2; PointEvaluator.Base evaluator = (TurnCount / 3 * 2) < CurrentTurn ? PointEvaluator_Normal : PointEvaluator_AreaCount; SearchState state = new SearchState(MyBoard, EnemyBoard, new Player(MyAgent1, MyAgent2), new Player(EnemyAgent1, EnemyAgent2), WaysPool); //競合判定 int K = KyogoTurn; //Kは1以上の整数 ngMove = null; for (i = 0; i < K; i++) { if (historyStates.Count < K) { break; } int id = historyStates.Count - 1 - i; if (id < 0 || state.Equals(historyStates[id]) == false) { break; } if (i + 1 < K && id > 0 && historyDecides[id].Equals(historyDecides[id - 1]) == false) { break; } } if (i == K) { int score = PointEvaluator_Normal.Calculate(ScoreBoard, state.MeBoard, 0) - PointEvaluator_Normal.Calculate(ScoreBoard, state.EnemyBoard, 0); if (score <= 0) { ngMove = historyDecides[historyDecides.Count - 1]; Log("[SOLVER] conclusion!, you cannot move to ", ngMove); } } //反復深化 for (; deepness <= maxDepth; deepness++) { NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, Math.Min(maxDepth - deepness, GreedyMaxDepth)); if (CancellationToken.IsCancellationRequested == false) { SolverResult = new Decided(dp[0].Agent1Way, dp[0].Agent2Way); } else { break; } Log("[SOLVER] deepness = {0}", deepness); } //履歴の更新 historyStates.Add(state); historyDecides.Add(SolverResult); }
protected override void Solve() { var myAgents = SearchFirstPlace(); Array.Clear(dp1, 0, dp1.Length); Array.Clear(dp2, 0, dp2.Length); int deepness = StartDepth; int maxDepth = (TurnCount - CurrentTurn) + 1; PointEvaluator.Base evaluator = (TurnCount / 3 * 2) < CurrentTurn ? PointEvaluator_Normal : PointEvaluator_Dispersion; SearchState state = new SearchState(MyBoard, EnemyBoard, myAgents, EnemyAgents, MySurroundedBoard, EnemySurroundedBoard); int score = 0; for (uint x = 0; x < ScoreBoard.GetLength(0); ++x) { for (uint y = 0; y < ScoreBoard.GetLength(1); ++y) { if (MyBoard[x, y]) { score += ScoreBoard[x, y]; } else if (MySurroundedBoard[x, y]) { score += Math.Abs(ScoreBoard[x, y]); } else if (EnemyBoard[x, y]) { score -= ScoreBoard[x, y]; } else if (EnemySurroundedBoard[x, y]) { score -= Math.Abs(ScoreBoard[x, y]); } } } Log("TurnCount = {0}, CurrentTurn = {1}", TurnCount, CurrentTurn); //if (!(lastTurnDecided is null)) Log("IsAgent1Moved = {0}, IsAgent2Moved = {1}, lastTurnDecided = {2}", IsAgent1Moved, IsAgent2Moved, lastTurnDecided); if (!(lastTurnDecided is null) && score > 0) //勝っている状態で競合していたら { int i; for (i = 0; i < AgentsCount; ++i) { if (IsAgentsMoved[i]) { break; } } if (i == AgentsCount) { SolverResultList.Add(lastTurnDecided); return; } } for (; deepness <= maxDepth; deepness++) { Decided resultList = new Decided(); //普通にNegaMaxをして、最善手を探す for (int agent = 0; agent < AgentsCount; ++agent) { if (MyAgentsState[agent] == AgentState.NonPlaced) { continue; } NegaMax(deepness, state, int.MinValue + 1, 0, evaluator, null, agent); } var res = dp1[0]; for (int agent = 0; agent < AgentsCount; ++agent) { if (MyAgentsState[agent] == AgentState.NonPlaced) { res[agent] = myAgents[agent]; } } Decision best1 = new Decision((byte)AgentsCount, res, agentStateAry); resultList.Add(best1); //競合手.Agent1 == 最善手.Agent1 && 競合手.Agent2 == 最善手.Agent2になった場合、競合手をngMoveとして探索をおこない、最善手を探す for (int i = 0; i < AgentsCount; ++i) { if (IsAgentsMoved[i] || (!(lastTurnDecided is null) && lastTurnDecided.Agents[i] != best1.Agents[i])) { break; } if (i < AgentsCount - 1) { continue; } for (int agent = 0; agent < AgentsCount; ++agent) { if (MyAgentsState[agent] == AgentState.NonPlaced) { continue; } NegaMax(deepness, state, int.MinValue + 1, 0, evaluator, best1, agent); } res = dp2[0]; for (int agent = 0; agent < AgentsCount; ++agent) { if (MyAgentsState[agent] == AgentState.NonPlaced) { res[agent] = myAgents[agent]; } } Decision best2 = new Decision((byte)AgentsCount, res, agentStateAry); resultList.Add(best2); } if (CancellationToken.IsCancellationRequested == false) { SolverResultList = resultList; if (SolverResultList.Count == 2 && score <= 0) //現時点で引き分けか負けていたら競合を避けるのを優先してみる(デバッグ用) { var tmp = SolverResultList[0]; SolverResultList[0] = SolverResultList[1]; SolverResultList[1] = tmp; Log("[SOLVER] Swaped! {0} {1}", SolverResult.Agents[0], SolverResult.Agents[1]); } Log("[SOLVER] SolverResultList.Count = {0}, score = {1}", SolverResultList.Count, score); } else { return; } Log("[SOLVER] deepness = {0}", deepness); } }
public void OnDecided(Decided decided) { _decided = decided; gameManager.viewModel.MainWindowDispatcher.Invoke(decidedMethod); }
private Decided SolveSub(int deepness) { int alpha = int.MinValue + 1; int beta = int.MaxValue; int result = int.MinValue; Player Killer = new Player(new Point(114, 114), new Point(114, 114)); var nextMe = MoveOrderling(IsCrossPainted(MyAgent1, MyBoard) ? 1 : 2, IsCrossPainted(MyAgent2, MyBoard) ? 1 : 2, ScoreBoard, MyBoard, EnemyBoard, new Player(MyAgent1, MyAgent2), new Player(EnemyAgent1, EnemyAgent2), 0); Decided returnValue = null; for (int i = 0; i < nextMe.Count; i++) { var nextMeValue = nextMe[i].Value; Player newMe = new Player(MyAgent1, MyAgent2); newMe.Agent1 += nextMeValue.Agent1; newMe.Agent2 += nextMeValue.Agent2; var movable = Checker.MovableCheck(MyBoard, EnemyBoard, newMe, new Player(EnemyAgent1, EnemyAgent2)); if (!movable.IsMovable) { continue; } int current = 0; var newMeBoard = MyBoard; if (movable.IsEraseNeeded) { var newEnBoard = EnemyBoard; if (movable.Me1 == Rule.MovableResultType.EraseNeeded) { newEnBoard[newMe.Agent1] = false; newMe.Agent1 = MyAgent1; } else { newMeBoard[newMe.Agent1] = true; } if (movable.Me2 == Rule.MovableResultType.EraseNeeded) { newEnBoard[newMe.Agent2] = false; newMe.Agent2 = MyAgent2; } else { newMeBoard[newMe.Agent2] = true; } current = Mini(deepness - 1, ScoreBoard, newMeBoard, newEnBoard, newMe, new Player(EnemyAgent1, EnemyAgent2), Math.Max(result, alpha), beta, 1); } else { newMeBoard[newMe.Agent1] = true; newMeBoard[newMe.Agent2] = true; current = Mini(deepness - 1, ScoreBoard, newMeBoard, EnemyBoard, newMe, new Player(EnemyAgent1, EnemyAgent2), Math.Max(result, alpha), beta, 1); } if (result < current) { result = current; dp[0].UpdateScore(result, nextMeValue.Agent1, nextMeValue.Agent2); returnValue = new Decided(nextMeValue.Agent1, nextMeValue.Agent2); } if (result >= beta) { return(returnValue); } } return(returnValue); }
private void NoBtn_Clicked(object sender, MouseButtonEventArgs e) { Decided?.Invoke(false); }
private void YesBtn_Clicked(object sender, MouseButtonEventArgs e) { Decided?.Invoke(true); }
protected override void Solve() { var tmp = MoveOrderling(ScoreBoard, MyBoard, EnemyBoard, new Player(MyAgent1, MyAgent2), new Player(EnemyAgent1, EnemyAgent2))[0]; SolverResult = new Decided(tmp.Value.Agent1, tmp.Value.Agent2); }
//遷移順を決める. 「この関数においては」MeBoard…手番プレイヤのボード, Me…手番プレイヤ、とします。 //引数: stateは手番プレイヤが手を打つ前の探索状態、(way1[i], way2[i])はi番目の合法手(移動量)です。 //以下のルールで優先順を決めます. //ルール1. Killer手(優先したい手)があれば、それを優先する //ルール2. 次のmoveで得られる「タイルポイント」の合計値が大きい移動(の組み合わせ)を優先する。 //ルール2では, タイル除去によっても「タイルポイント」が得られるとして計算する。 private void SortMoves(sbyte[,] ScoreBoard, SearchState state, Ways way, int deep, Decided ngMove) { Player Killer; if (ngMove is null) { Killer = dp1[deep].Score == int.MinValue ? new Player(new Point(114, 514), new Point(114, 514)) : new Player(state.Me.Agent1 + dp1[deep].Agent1Way, state.Me.Agent2 + dp1[deep].Agent2Way); } else { Killer = dp2[deep].Score == int.MinValue ? new Player(new Point(114, 514), new Point(114, 514)) : new Player(state.Me.Agent1 + dp2[deep].Agent1Way, state.Me.Agent2 + dp2[deep].Agent2Way); } for (int i = 0; i < way.Count; i++) { int score = 0; Point next1 = state.Me.Agent1 + way[i].Agent1Way; Point next2 = state.Me.Agent2 + way[i].Agent2Way; if (Killer.Agent1 == next1 && Killer.Agent2 == next2) { score = 100; } if (state.EnemyBoard[next1]) { score += ScoreBoard[next1.X, next1.Y]; } //タイル除去によって有利になる else if (!state.MeBoard[next1]) { score += ScoreBoard[next1.X, next1.Y]; } //移動でMeの陣地が増えて有利になる if (state.EnemyBoard[next2]) { score += ScoreBoard[next2.X, next2.Y]; } else if (!state.MeBoard[next2]) { score += ScoreBoard[next2.X, next2.Y]; } way[i].Point = score; } way.Sort(); }
//1ターン = 深さ2 protected override void Solve() { for (int i = 0; i < 50; ++i) { dp1[i].Score = int.MinValue; dp2[i].Score = int.MinValue; } int deepness = StartDepth; int maxDepth = (TurnCount - CurrentTurn) * 2 + 2; PointEvaluator.Base evaluator = (TurnCount / 3 * 2) < CurrentTurn ? PointEvaluator_Normal : PointEvaluator_Dispersion; SearchState state = new SearchState(MyBoard, EnemyBoard, new Player(MyAgent1, MyAgent2), new Player(EnemyAgent1, EnemyAgent2), WaysPool); int score = PointEvaluator_Normal.Calculate(ScoreBoard, state.MeBoard, 0) - PointEvaluator_Normal.Calculate(ScoreBoard, state.EnemyBoard, 0); Log("TurnCount = {0}, CurrentTurn = {1}", TurnCount, CurrentTurn); if (!(lastTurnDecided is null)) { Log("IsAgent1Moved = {0}, IsAgent2Moved = {1}, lastTurnDecided = {2}", IsAgent1Moved, IsAgent2Moved, lastTurnDecided); } if (!(lastTurnDecided is null) && IsAgent1Moved == false && IsAgent2Moved == false && score > 0) //勝っている状態で競合していたら { SolverResultList.Add(lastTurnDecided); return; } for (; deepness <= maxDepth; deepness++) { DecidedEx resultList = new DecidedEx(); int greedyDepth = Math.Min(greedyMaxDepth, maxDepth - deepness); if ((deepness + greedyDepth) % 2 == 1 && greedyDepth > 0) { greedyDepth--; } //普通にNegaMaxをして、最善手を探す NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, null, greedyDepth); Decided best1 = new Decided(dp1[0].Agent1Way, dp1[0].Agent2Way); resultList.Add(best1); //競合手.Agent1 == 最善手.Agent1 && 競合手.Agent2 == 最善手.Agent2になった場合、競合手をngMoveとして探索をおこない、最善手を探す if ((IsAgent1Moved == false && lastTurnDecided.MeAgent1.Equals(best1.MeAgent1)) && (IsAgent2Moved == false && lastTurnDecided.MeAgent2.Equals(best1.MeAgent2))) { NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, best1, greedyDepth); Decided best2 = new Decided(dp2[0].Agent1Way, dp2[0].Agent2Way); resultList.Add(best2); } if (CancellationToken.IsCancellationRequested == false) { SolverResultList = resultList; if (SolverResultList.Count == 2 && score <= 0) //現時点で引き分けか負けていたら競合を避けるのを優先してみる(デバッグ用) { var tmp = SolverResultList[0]; SolverResultList[0] = SolverResultList[1]; SolverResultList[1] = tmp; Log("[SOLVER] Swaped! {0} {1}", SolverResult.MeAgent1, SolverResult.MeAgent2); } Log("[SOLVER] SolverResultList.Count = {0}, score = {1}", SolverResultList.Count, score); } else { return; } Log("[SOLVER] deepness = {0}", deepness); } }
//1ターン = 深さ2 protected override void Solve() { for (int i = 0; i < 50; ++i) { dp1[i].Score = int.MinValue; dp2[i].Score = int.MinValue; } int deepness = StartDepth; int maxDepth = (TurnCount - CurrentTurn) * 2 + 2; PointEvaluator.Base evaluator = (TurnCount / 3 * 2) < CurrentTurn ? PointEvaluator_Normal : PointEvaluator_Distance; SearchState state = new SearchState(MyBoard, EnemyBoard, MyAgents, EnemyAgents); int score = PointEvaluator_Normal.Calculate(ScoreBoard, state.MeBoard, 0, MyAgents, EnemyAgents) - PointEvaluator_Normal.Calculate(ScoreBoard, state.EnemyBoard, 0, EnemyAgents, MyAgents); Log("TurnCount = {0}, CurrentTurn = {1}", TurnCount, CurrentTurn); if (!(lastTurnDecided is null)) { StringBuilder sb = new StringBuilder("AgentMoved: {"); for (int i = 0; i < AgentsCount; ++i) { sb.Append(IsAgentsMoved[i]); sb.Append(", "); } string ismoved = sb.ToString(); Log("{0}}}, lastTurnDecided = {2}", ismoved.Substring(0, ismoved.Length - 2), lastTurnDecided); } if (!(lastTurnDecided is null) && IsAgentsMoved.GetEnumerable(AgentsCount).All(b => b == false) && score > 0) //勝っている状態で競合していたら { SolverResultList.Add(lastTurnDecided); return; } for (; deepness <= maxDepth; deepness++) { Decided resultList = new Decided(); int greedyDepth = Math.Min(greedyMaxDepth, maxDepth - deepness); if ((deepness + greedyDepth) % 2 == 1 && greedyDepth > 0) { greedyDepth--; } //普通にNegaMaxをして、最善手を探す NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, null, greedyDepth); Decision best1 = new Decision(Unsafe8Array <VelocityPoint> .Create(dp1[0].Ways.GetEnumerable(AgentsCount).Select(x => x.Direction).ToArray())); resultList.Add(best1); //競合手.Agent == 最善手.Agent の数が半数以上になった場合、競合手をngMoveとして探索をおこない、最善手を探す int UnMoveAgentNum = 0; for (int i = 0; i < AgentsCount; ++i) { if (IsAgentsMoved[i] == false && lastTurnDecided.Agents[i] == best1.Agents[i]) { ++UnMoveAgentNum; } } if (UnMoveAgentNum > AgentsCount / 2) { NegaMax(deepness, state, int.MinValue + 1, int.MaxValue, 0, evaluator, best1, greedyDepth); Decision best2 = new Decision(Unsafe8Array <VelocityPoint> .Create(dp2[0].Ways.GetEnumerable(AgentsCount).Select(x => x.Direction).ToArray())); resultList.Add(best2); } if (CancellationToken.IsCancellationRequested == false) { SolverResultList = resultList; if (SolverResultList.Count == 2 && score <= 0) //現時点で引き分けか負けていたら競合を避けるのを優先してみる(デバッグ用) { var tmp = SolverResultList[0]; SolverResultList[0] = SolverResultList[1]; SolverResultList[1] = tmp; Log("[SOLVER] Swaped! {0} {1}", SolverResult.Agents[0], SolverResult.Agents[1]); } Log("[SOLVER] SolverResultList.Count = {0}, score = {1}", SolverResultList.Count, score); } else { return; } Log("[SOLVER] deepness = {0}", deepness); } }