// モンテカルロシミュレーション(基地航空隊がない場合) 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); }
// モンテカルロシミュレーション(基地航空隊がある場合) 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); }