Esempio n. 1
0
        //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);
            }
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
 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);
                }
            }
Esempio n. 5
0
        //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);
        }
Esempio n. 6
0
 protected override void EndSolve(object sender, EventArgs e)
 {
     base.EndSolve(sender, e);
     lastTurnDecided = SolverResultList[0];  //0番目の手を指したとする。(次善手を人間が選んで競合した~ということがなければOK)
 }
Esempio n. 7
0
        //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);
            }
        }
Esempio n. 8
0
 public void OnDecided(Decided decided)
 {
     gameManager.ClearDecisions(managerNum);
     _decided = decided;
     gameManager.viewModel.MainWindowDispatcher.Invoke(decidedMethod);
 }
Esempio n. 9
0
        //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);
        }
Esempio n. 10
0
        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);
            }
        }
Esempio n. 11
0
 public void OnDecided(Decided decided)
 {
     _decided = decided;
     gameManager.viewModel.MainWindowDispatcher.Invoke(decidedMethod);
 }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
 private void NoBtn_Clicked(object sender, MouseButtonEventArgs e)
 {
     Decided?.Invoke(false);
 }
Esempio n. 14
0
 private void YesBtn_Clicked(object sender, MouseButtonEventArgs e)
 {
     Decided?.Invoke(true);
 }
Esempio n. 15
0
        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);
        }
Esempio n. 16
0
        //遷移順を決める.  「この関数においては」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();
        }
Esempio n. 17
0
        //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);
            }
        }
Esempio n. 18
0
        //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);
            }
        }