Ejemplo n.º 1
0
        // モンテカルロシミュレーション(基地航空隊がない場合)
        public static string MonteCarloImpl(Fleet friend, Fleet enemy, int simulationSize)
        {
            string output = "【モンテカルロシミュレーション】\n";

            output += $"反復回数:{simulationSize}回\n";
            // 初期状態を記録する
            var firstFriendAirsList = friend.AirsList;
            var firstEnemyAirsList  = enemy.AirsList;

            // 保存用バッファを用意する
            MakeLists(firstFriendAirsList, out friendKammusuList, out friendLeaveAirsList);
            MakeLists(firstEnemyAirsList, out enemyKammusuList, out enemyLeaveAirsList);
            // 反復計算を行う
            var friendAirsList    = DeepCopyHelper.DeepCopy(firstFriendAirsList);
            var enemyAirsList     = DeepCopyHelper.DeepCopy(firstEnemyAirsList);
            var AirWarStatusCount = new List <int> {
                0, 0, 0, 0, 0
            };
            int unitCount = UnitCount(enemy.Unit.Count, friend.Unit.Count);

            for (int i = 0; i < simulationSize; ++i)
            {
                // 状態を初期化する
                CopyAirsList(firstFriendAirsList, friendAirsList);
                CopyAirsList(firstEnemyAirsList, enemyAirsList);
                #region ステージ1:航空戦
                // 制空値を計算する
                int friendAirValue = NowAirValue(friend, unitCount, friendAirsList);
                int enemyAirValue  = NowAirValue(enemy, unitCount, enemyAirsList);
                // 制空状態を判断する
                AirWarStatus airWarStatus = CalcAirWarStatus(friendAirValue, enemyAirValue);
                ++AirWarStatusCount[(int)airWarStatus];
                // 割合撃墜を行う
                St1FriendBreak(friend, unitCount, friendAirsList, airWarStatus);
                St1EnemyBreak(enemy, unitCount, enemyAirsList, airWarStatus);
                #endregion
                #region ステージ2:対空砲火
                var friendCutInType = GetCutInType(friend);
                var enemyCutInType  = GetCutInType(enemy);
                St2FriendBreak(friend, enemy, unitCount, friendAirsList, enemyCutInType);
                St2EnemyBreak(enemy, friend, unitCount, enemyAirsList, friendCutInType);
                #endregion
                // 残数を記録する
                MemoLeaveList(friend, friendAirsList, friendKammusuList, friendLeaveAirsList);
                MemoLeaveList(enemy, enemyAirsList, enemyKammusuList, enemyLeaveAirsList);
            }
            // 結果を書き出す
            output += "【制空状態】\n";
            output += "本隊";
            for (int i = 0; i < (int)AirWarStatus.Size; ++i)
            {
                var i2 = (AirWarStatus)i;
                output += $" {i2.ToStr()}:{Math.Round(100.0 * AirWarStatusCount[i] / simulationSize, 1)}%";
            }
            output += "\n";
            output += "【棒立ち率 [スロット毎の全滅率]】\n";
            output += "自艦隊:\n";
            for (int i = 0; i < friendKammusuList.Count; ++i)
            {
                for (int j = 0; j < friendKammusuList[i].Count; ++j)
                {
                    int sum = firstFriendAirsList[i][j].Sum();
                    if (sum > 0)
                    {
                        output += $"{friend.Unit[i].Kammusu[j].Name}→{Math.Round(100.0 * friendKammusuList[i][j] / simulationSize, 1)}%";
                        for (int k = 0; k < friend.Unit[i].Kammusu[j].SlotCount; ++k)
                        {
                            if (firstFriendAirsList[i][j][k] > 0)
                            {
                                output += $" {k + 1}:[{Math.Round(100.0 * friendLeaveAirsList[i][j][k][0] / simulationSize, 1)}%]";
                            }
                        }
                        output += "\n";
                    }
                }
            }
            output += "敵艦隊:\n";
            for (int i = 0; i < enemyKammusuList.Count; ++i)
            {
                for (int j = 0; j < enemyKammusuList[i].Count; ++j)
                {
                    int sum = firstEnemyAirsList[i][j].Sum();
                    if (sum > 0)
                    {
                        output += $"{enemy.Unit[i].Kammusu[j].Name}→{Math.Round(100.0 * enemyKammusuList[i][j] / simulationSize, 1)}%";
                        for (int k = 0; k < enemy.Unit[i].Kammusu[j].SlotCount; ++k)
                        {
                            if (firstEnemyAirsList[i][j][k] > 0)
                            {
                                output += $" {k + 1}:[{Math.Round(100.0 * enemyLeaveAirsList[i][j][k][0] / simulationSize, 1)}%]";
                            }
                        }
                        output += "\n";
                    }
                }
            }
            return(output);
        }
Ejemplo n.º 2
0
        // モンテカルロシミュレーション(基地航空隊がある場合)
        public static string MonteCarloImpl(Fleet friend, Fleet enemy, LandBase landBase, int simulationSize)
        {
            string output = "【モンテカルロシミュレーション】\n";

            output += $"反復回数:{simulationSize}回\n";
            // 初期状態を記録する
            var firstFriendAirsList   = friend.AirsList;
            var firstLandBaseAirsList = landBase.AirsList;
            var firstEnemyAirsList    = enemy.AirsList;

            // 保存用バッファを用意する
            MakeLists(firstFriendAirsList, out friendKammusuList, out friendLeaveAirsList);
            MakeLists(firstLandBaseAirsList, out landBaseList, out landBaseLeaveAirsList);
            MakeLists(firstEnemyAirsList, out enemyKammusuList, out enemyLeaveAirsList);
            // 反復計算を行う
            var friendAirsList    = DeepCopyHelper.DeepCopy(firstFriendAirsList);
            var landBaseAirsList  = DeepCopyHelper.DeepCopy(firstLandBaseAirsList);
            var enemyAirsList     = DeepCopyHelper.DeepCopy(firstEnemyAirsList);
            var AirWarStatusCount = new List <List <int> >();

            for (int ti = 0; ti <= landBase.TeamCount; ++ti)
            {
                AirWarStatusCount.Add(new List <int> {
                    0, 0, 0, 0, 0
                });
            }
            int unitCount = UnitCount(enemy.Unit.Count, friend.Unit.Count);

            for (int i = 0; i < simulationSize; ++i)
            {
                // 状態を初期化する
                CopyAirsList(firstFriendAirsList, friendAirsList);
                CopyAirsList(firstLandBaseAirsList, landBaseAirsList);
                CopyAirsList(firstEnemyAirsList, enemyAirsList);
                // 基地航空隊
                for (int ti = 0; ti < landBase.TeamCount; ++ti)
                {
                    for (int ai = 0; ai < landBase.AttackCount[ti]; ++ai)
                    {
                        #region ステージ1:航空戦
                        // 制空値を計算する
                        int landBaseAirValue = NowAirValueX(landBase, landBaseAirsList, ti);
                        int enemyAirValue_   = NowAirValueX(enemy, enemy.Unit.Count, enemyAirsList);
                        // 制空状態を判断する
                        AirWarStatus airWarStatus_ = CalcAirWarStatus(landBaseAirValue, enemyAirValue_);
                        // 割合撃墜を行う
                        // 基地航空隊を集中運用した際、1回目に来た際撃墜された分は
                        // 2回目発動前に自動回復する(ここでの資源消費はないが熟練度はハゲる)
                        if (landBase.AttackCount[ti] == 1 || ai == 1)
                        {
                            ++AirWarStatusCount[ti][(int)airWarStatus_];
                            St1LandBaseBreak(landBase, landBaseAirsList, ti, airWarStatus_);
                        }
                        St1EnemyBreak(enemy, enemy.Unit.Count, enemyAirsList, airWarStatus_);
                        #endregion
                        if (landBase.AttackCount[ti] == 1 || ai == 1)
                        {
                            #region ステージ2:対空砲火
                            var enemyCutInType_ = GetCutInType(enemy);
                            St2LandBaseBreak(landBase, enemy, landBaseAirsList, ti, enemyCutInType_);
                            #endregion
                        }
                    }
                }
                // 艦隊戦
                #region ステージ1:航空戦
                // 制空値を計算する
                int friendAirValue = NowAirValue(friend, unitCount, friendAirsList);
                int enemyAirValue  = NowAirValue(enemy, unitCount, enemyAirsList);
                // 制空状態を判断する
                AirWarStatus airWarStatus = CalcAirWarStatus(friendAirValue, enemyAirValue);
                ++AirWarStatusCount[landBase.TeamCount][(int)airWarStatus];
                // 割合撃墜を行う
                St1FriendBreak(friend, unitCount, friendAirsList, airWarStatus);
                St1EnemyBreak(enemy, unitCount, enemyAirsList, airWarStatus);
                #endregion
                #region ステージ2:対空砲火
                var friendCutInType = GetCutInType(friend);
                var enemyCutInType  = GetCutInType(enemy);
                St2FriendBreak(friend, enemy, unitCount, friendAirsList, enemyCutInType);
                St2EnemyBreak(enemy, friend, unitCount, enemyAirsList, friendCutInType);
                #endregion
                // 残数を記録する
                MemoLeaveList(friend, friendAirsList, friendKammusuList, friendLeaveAirsList);
                MemoLeaveList(landBase, landBaseAirsList, landBaseList, landBaseLeaveAirsList);
                MemoLeaveList(enemy, enemyAirsList, enemyKammusuList, enemyLeaveAirsList);
            }
            // 結果を書き出す
            output += "【制空状態】\n";
            for (int ti = 0; ti <= landBase.TeamCount; ++ti)
            {
                output += (ti == landBase.TeamCount ? "本隊" : $"基地-{ti + 1}");
                for (int i = 0; i < (int)AirWarStatus.Size; ++i)
                {
                    var i2 = (AirWarStatus)i;
                    output += $" {i2.ToStr()}:{Math.Round(100.0 * AirWarStatusCount[ti][i] / simulationSize, 1)}%";
                }
                output += "\n";
            }
            output += "【棒立ち率 [スロット毎の全滅率]】\n";
            output += "自艦隊:\n";
            for (int i = 0; i < friendKammusuList.Count; ++i)
            {
                for (int j = 0; j < friendKammusuList[i].Count; ++j)
                {
                    int sum = firstFriendAirsList[i][j].Sum();
                    if (sum > 0)
                    {
                        output += $"{friend.Unit[i].Kammusu[j].Name}→{Math.Round(100.0 * friendKammusuList[i][j] / simulationSize, 1)}%";
                        for (int k = 0; k < friend.Unit[i].Kammusu[j].SlotCount; ++k)
                        {
                            if (firstFriendAirsList[i][j][k] > 0)
                            {
                                output += $" {k+1}:[{Math.Round(100.0 * friendLeaveAirsList[i][j][k][0]/ simulationSize, 1)}%]";
                            }
                        }
                        output += "\n";
                    }
                }
            }
            output += "基地航空隊:\n";
            for (int ti = 0; ti < landBase.TeamCount; ++ti)
            {
                output += $"基地-{ti + 1}→{Math.Round(100.0 * landBaseList[ti] / simulationSize, 1)}%";
                for (int wi = 0; wi < landBase.Team[ti].Weapon.Count; ++wi)
                {
                    if (firstLandBaseAirsList[ti][wi] > 0)
                    {
                        output += $" {wi + 1}:[{Math.Round(100.0 * landBaseLeaveAirsList[ti][wi][0] / simulationSize, 1)}%]";
                    }
                }
                output += "\n";
            }
            output += "敵艦隊:\n";
            for (int i = 0; i < enemyKammusuList.Count; ++i)
            {
                for (int j = 0; j < enemyKammusuList[i].Count; ++j)
                {
                    int sum = firstEnemyAirsList[i][j].Sum();
                    if (sum > 0)
                    {
                        output += $"{enemy.Unit[i].Kammusu[j].Name}→{Math.Round(100.0 * enemyKammusuList[i][j] / simulationSize, 1)}%";
                        for (int k = 0; k < enemy.Unit[i].Kammusu[j].SlotCount; ++k)
                        {
                            if (firstEnemyAirsList[i][j][k] > 0)
                            {
                                output += $" {k + 1}:[{Math.Round(100.0 * enemyLeaveAirsList[i][j][k][0] / simulationSize, 1)}%]";
                            }
                        }
                        output += "\n";
                    }
                }
            }
            return(output);
        }