//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); } }
//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); } }
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); } }