/// <summary> /// コンストラクタ /// </summary> /// <param name="gameData">試合のデータ</param> public DefenseActionManger(GameData gameData) { GameData = gameData; // フィールドの初期化 GameData.DefenseTermKind = DefenseTermKind.Finished; BaseCoverPosition = new Dictionary<int, DefensePosition>(); BaseCoverRemainingTime = new Dictionary<int, int>(); }
/// <summary> /// 初期化処理 /// </summary> /// <param name="gameData"></param> public void Initialize(GameData gameData) { // フィールドの設定 GameData = gameData; // 大会情報の表示 GameInfomation.Text = EVManager.Instance.CurrentCupStatus; // 先攻・後攻の表示 if (GameData.UserTeamTopOrBottom) { TopOrBottomText1.Text = "先攻"; TopOrBottomText2.Text = "後攻"; } else { TopOrBottomText1.Text = "後攻"; TopOrBottomText2.Text = "先攻"; } // チーム名の表示 UserTeamName.Text = GameData.UserTeamSetting.Name; ComTeamName.Text = GameData.ComTeamSetting.Name; // 打順リストボックスの作成 List<ValueClass> orders = new List<ValueClass>(); for (int i = 1; i <= 9; i++) { orders.Add(new ValueClass() { Value = i }); } UserTeamOrderNumberList.ItemsSource = orders; ComTeamOrderNumberList.ItemsSource = orders; // スコアボードの初期化 ScoreBoard.Initialize(GameData); // UI更新 UpdateControlInternal(); // ユーザが操作できないように透明のコントロールを配置 GardText.Visibility = Visibility.Visible; }
/// <summary> /// 初期化処理 /// </summary> /// <param name="gameData"></param> public void Initialize(GameData gameData) { // スコアボードのチーム名 TopTeamInitial.Text = gameData.TopTeamSetting.InitialName; BottomTeamInitial.Text = gameData.BottomTeamSetting.InitialName; // スコアボードのイニング数 Ininng1.Text = "一"; Ininng2.Text = "ニ"; Ininng3.Text = "三"; Ininng4.Text = "四"; Ininng5.Text = "五"; Ininng6.Text = "六"; Ininng7.Text = "七"; Ininng8.Text = "八"; Ininng9.Text = "九"; Ininng10.Text = "十"; // スコアボードの得点 Score1_1.Text = string.Empty; Score1_2.Text = string.Empty; Score1_3.Text = string.Empty; Score1_4.Text = string.Empty; Score1_5.Text = string.Empty; Score1_6.Text = string.Empty; Score1_7.Text = string.Empty; Score1_8.Text = string.Empty; Score1_9.Text = string.Empty; Score1_10.Text = string.Empty; Score2_1.Text = string.Empty; Score2_2.Text = string.Empty; Score2_3.Text = string.Empty; Score2_4.Text = string.Empty; Score2_5.Text = string.Empty; Score2_6.Text = string.Empty; Score2_7.Text = string.Empty; Score2_8.Text = string.Empty; Score2_9.Text = string.Empty; Score2_10.Text = string.Empty; }
/// <summary> /// 構築 /// </summary> /// <param name="topTeamSetting">先行チーム設定</param> /// <param name="bottomTeamSetting">後攻チーム設定</param> /// <param name="userTeamTopOrBottom"></param> public GameManager(TeamSetting topTeamSetting, TeamSetting bottomTeamSetting, bool userTeamTopOrBottom) { // リストフィールドの初期化 CurrentInningMidwayShowMember = new List<GameMember>(); // デフォルトメンバ設定を元にこの試合用のメンバ設定を作成 topTeamSetting.CreateCurrentMembersFromDefault(); bottomTeamSetting.CreateCurrentMembersFromDefault(); // 試合データの作成 GameData = new GameData(topTeamSetting, bottomTeamSetting, userTeamTopOrBottom); // フィールドの初期化 DefenseActionManger = new DefenseActionManger(GameData); // 守備位置の初期化 DefenseActionManger.InitializeDefensePosition(); // イベント接続 DefenseActionManger.PassedDefenseTerm += (DefenseActionManger_PassedDefenseTerm); DefenseActionManger.AddedRunScore += (DefenseActionManger_AddedRunScore); DefenseActionManger.ReflectedFense += (DefenseActionManger_ReflectedFense); DefenseActionManger.JudgedSafeOrOut += new Action<bool>(DefenseActionManger_JudgedSafeOrOut); DefenseActionManger.OccurError += DefenseActionManger_OccurError; DefenseActionManger.OccurFoul += DefenseActionManger_OccurFoul; DefenseActionManger.CatchBoll += DefenseActionManger_CatchBoll; DefenseActionManger.ThrowBoll += DefenseActionManger_ThrowBoll; DefenseActionManger.TurnForThrow += DefenseActionMangerOnTurnForThrow; // 試合進行フェーズの初期値は投球フェーズにする GameProgressKind = GameProgressKind.PitchingBoll; // 準備フェーズがないため、先頭打者に対しての守備変更をここで実行する UpdateDefenseShift(); // 高速試合モードの設定 ChangeGameMode(); }
/// <summary> /// メンバ能力の取得 /// </summary> /// <param name="baseNumber">元の塁の番号(1~3)</param> /// <param name="gameData">試合のデータ</param> /// <returns>メンバ能力</returns> public static GameMemberAbility GetRunnerAbility(int baseNumber, GameData gameData) { GameMemberAbility memberAbility; switch (baseNumber) { case 1: memberAbility = gameData.FirstRunnerAbirity; break; case 2: memberAbility = gameData.SecondRunnerAbirity; break; case 3: memberAbility = gameData.ThirdRunnerAbirity; break; default: throw new Exception("Invalid baseNumber"); } return memberAbility; }
/// <summary> /// 盗塁可能かどうかの盗塁判断タイプを智力依存でなく事実を取得する /// </summary> /// <param name="gameData">試合のデータ</param> /// <returns>盗塁判断タイプ</returns> public static StealJudgeType GetRealStealJudgeType(GameData gameData) { StealJudgeType stealJudgeType = StealJudgeType.Invalid; // ランナーがいないか満塁の場合は何もしない if (gameData.AllRunnerMembers.Count == 0 || gameData.AllRunnerMembers.Count == 3) { return stealJudgeType; } // 盗塁対象外ならそれを返す int baseNumber = gameData.StealTargetRunnerNumber; if (baseNumber == 0) { return stealJudgeType; } // 盗塁阻止にかかる時間を取得 GameMemberAbility catcherAbility = new GameMemberAbility(gameData.CurrentDefenseTeam.GetMember(DefensePosition.Catcher), gameData); int throwTime = GetThrowTimeForSteal(baseNumber + 1, catcherAbility); // 盗塁にかかる時間を取得 int stealTimeByFastBall = GetStealTimeByFastBall(baseNumber, gameData); int stealTimeByBreakingBall = GetStealTimeByBreakingBall(baseNumber, gameData); int stealTimeByPitchOut = GetStealTimeByPitchOut(baseNumber, gameData); if (stealTimeByPitchOut < throwTime) { stealJudgeType = StealJudgeType.Success; } else if (stealTimeByFastBall < throwTime) { stealJudgeType = StealJudgeType.SuccessIfFastBoll; } else if (stealTimeByBreakingBall < throwTime) { stealJudgeType = StealJudgeType.SuccessIfBreakingBoll; } else { stealJudgeType = StealJudgeType.Impossible; } return stealJudgeType; }
/// <summary> /// 球種変更による補正値を算出する /// </summary> /// <param name="gameData">試合のデータ</param> /// <param name="isFastBall">直球か変化球か</param> /// <returns>算出した値</returns> public static double GetOffsetValueByChabgeBollKind(GameData gameData, bool isFastBall) { // 初球の場合は補正なし if (gameData.ContinueingSameBollCount == 0) { return 0; } if (gameData.PreviousBollKind != isFastBall) { // 前回と異なる球種の場合、球速または変化球をプラス補正 // (2球続けて同じ球種の後にプラス補正、1球でプラスにすると交互に投げるのが最強になってしまうため) double offset = 0; for (int count = 1; count < gameData.ContinueingSameBollCount; count++) { offset += Constants.ChangeBollKindOffset * count; } return offset; } else { // 同じ球種を続けるとマイナス補正 // (この時点の計算式では、前回までに連続した球数のため // 2球続けた場合に1回分のマイナス補正となる) int count = gameData.ContinueingSameBollCount < 5 ? gameData.ContinueingSameBollCount : 5; double offset = (-1) * Constants.ChangeBollKindOffset * count; return offset; } }
/// <summary> /// 初期化 /// </summary> public void Initialize(GameData gameData) { // フィールドの初期設定 GameData = gameData; // 大会情報 CupInfo.Text = EVManager.Instance.CurrentCupStatus; if (gameData.IsEnd) { // 勝利か敗北か if (GameData.RunScoreDeltaForUser > 0) { SoundManager.PlayBGM(SoundBGMKind.tr23_Victory_in); WinOrLoseText.Text = "勝利"; } else if (GameData.RunScoreDeltaForUser < 0) { SoundManager.PlayBGM(SoundBGMKind.tr28_Naraku); WinOrLoseText.Text = "敗北"; } else { // 引き分けの場合はBGM変更なし WinOrLoseText.Text = "引き分け"; } } else { // 試合中のスコア表示の場合は空文字を設定 WinOrLoseText.Text = string.Empty; } // チーム設定 UserTeamName.Text = GameData.UserTeamSetting.Name; ComTeamName.Text = GameData.ComTeamSetting.Name; UserScore.Text = GameData.UserTeamRunScore.ToString(); ComScore.Text = GameData.ComTeamRunScore.ToString(); // スコアボードの更新 ScoreBoard1.Initialize(gameData); ScoreBoard1.Update(gameData, false); if (gameData.CurrentInning <= 10) { ScoreBoard2.Visibility = Visibility.Collapsed; } else { ScoreBoard2.Visibility = Visibility.Visible; ScoreBoard2.Initialize(gameData); ScoreBoard2.Update(gameData); } // モードごとの表示 ChangeMode(ModeKind.Score); // 表示状態に変更 this.Visibility = Visibility.Visible; }
/// <summary> /// コンストラクタ /// </summary> /// <param name="gameData"></param> public BattingMissionManager(GameData gameData) { GameData = gameData; }
/// <summary> /// 対象のランナーが盗塁するか /// </summary> /// <param name="baseNumber">ランナー番号</param> /// <param name="gameData">試合のデータ</param> /// <param name="stealJudgeType">盗塁判断タイプ</param> /// <returns>盗塁するか</returns> private static bool TryStealPerRunner(int baseNumber, GameData gameData, out StealJudgeType stealJudgeType) { // 盗塁阻止にかかる時間を取得 GameMemberAbility catcherAbility = new GameMemberAbility(gameData.CurrentDefenseTeam.GetMember(DefensePosition.Catcher), gameData); int throwTime = GetThrowTimeForSteal(baseNumber + 1, catcherAbility); // 盗塁にかかる時間を取得 int stealTimeByFastBall = GetStealTimeByFastBall(baseNumber, gameData); int stealTimeByBreakingBall = GetStealTimeByBreakingBall(baseNumber, gameData); int stealTimeByPitchOut = GetStealTimeByPitchOut(baseNumber, gameData); // メンバ能力の取得 GameMemberAbility memberAbility = GetRunnerAbility(baseNumber, gameData); // 状況によって積極盗塁と慎重盗塁を分ける // 慎重盗塁(ウエストでもいけるなら100%で実行、直球でもいけるなら確率で実行) { // 盗塁できないと誤判断する時間 int judgeTime = (int)GameMemberAbility.GetLowerValue(memberAbility.Wisdom, Constants.MaxWrongJudgeTimeForStealNotEnable); #region 盗塁判断タイプの設定 if (stealTimeByPitchOut + judgeTime < throwTime) { stealJudgeType = StealJudgeType.Success; } else if (stealTimeByFastBall + judgeTime < throwTime) { stealJudgeType = StealJudgeType.SuccessIfFastBoll; } else if (stealTimeByBreakingBall + judgeTime < throwTime) { stealJudgeType = StealJudgeType.SuccessIfBreakingBoll; } else { stealJudgeType = StealJudgeType.Impossible; } #endregion // ウエスト時に盗塁可能か if (stealTimeByPitchOut + judgeTime < throwTime) { // ウエスト時に盗塁可能と判断した場合、100%で盗塁する return true; } // 直球で盗塁可能か if (stealTimeByFastBall + judgeTime < throwTime) { // 盗塁可能であれば、アウトカウントごとに確率で判定 int value; if (gameData.OutCount == 0) { // 0アウトの場合 value = 30; } else if (gameData.OutCount == 1) { // 1アウトの場合 value = 50; } else { // 2アウトの場合 value = 70; } // 三盗は慎重に行うべきのため、半分の確率とする if (baseNumber == 2) { value /= 2; } return RandomCreater.GetPercentValue() < value; } } // 積極盗塁(2アウトの一塁ランナーの場合のみ) if (gameData.OutCount == 2 && baseNumber == 1 && gameData.AllRunnerMembers.Count == 1) { // 9回以降で2点以上負けている場合は盗塁しない if (gameData.CurrentInning >= 9 && gameData.RunScoreDeltaForAttackTeam <= -2) { return false; } // 試合中にすでに盗塁失敗している場合は実行確率低下 int downValue = gameData.CurrentAttackTeam.StealOutCount * 10; // 盗塁できると誤判断する時間 int judgeTime = (int)GameMemberAbility.GetLowerValue(memberAbility.Wisdom, Constants.MaxWrongJudgeTimeForStealForEnable); // ウエスト時に盗塁可能か if (stealTimeByPitchOut - judgeTime < throwTime) { // ウエスト時に盗塁可能と判断した場合、高確率で盗塁する // (誤判断で盗塁できない可能性があるため100%としない) return RandomCreater.GetPercentValue() < (80 - downValue); } // 直球で盗塁可能か if (stealTimeByFastBall - judgeTime < throwTime) { return RandomCreater.GetPercentValue() < (50 - downValue); } // 変化球で盗塁可能か if (stealTimeByBreakingBall - judgeTime < throwTime) { if (gameData.CurrentPitcherAbirity.Fastball - gameData.CurrentPitcherAbirity.Breakingball > 4) { // 直球の方が大幅に強い場合は、直球中心で投げる可能性が高いため盗塁はあまり狙わない return RandomCreater.GetPercentValue() < (10 - downValue); } else { // そうでなければ、変化球を投げることを願って盗塁する return RandomCreater.GetPercentValue() < (30 - downValue); } } } // いずれの条件にも該当しなければ盗塁しない return false; }
/// <summary> /// 盗塁するか /// </summary> /// <param name="gameData">試合のデータ</param> /// <returns>盗塁するか</returns> public static bool TrySteal(GameData gameData) { // デバッグでの確率検証中は盗塁しない if (Constants.IsDebugValidationMode) { return false; } // ランナーがいないか満塁の場合は何もしない if (gameData.AllRunnerMembers.Count == 0 || gameData.AllRunnerMembers.Count == 3) { return false; } StealJudgeType stealJudgeType; // 二塁ランナーの盗塁判断 if (gameData.ThirdRunnerMember == null && gameData.SecondRunnerMember != null) { return TryStealPerRunner(2, gameData, out stealJudgeType); } // 一塁ランナーの盗塁判断 if (gameData.SecondRunnerMember == null && gameData.FirstRunnerMember != null) { return TryStealPerRunner(1, gameData, out stealJudgeType); } // 条件に該当しなければ盗塁なし return false; }
/// <summary> /// 盗塁で次の塁までにかかる時間を取得する(変化球) /// </summary> /// <param name="baseNumber">盗塁するランナーのベース番号</param> /// <param name="gameData">試合のデータ</param> /// <returns>盗塁で次の塁までにかかる時間</returns> public static int GetStealTimeByBreakingBall(int baseNumber, GameData gameData) { // 想定する投球データを作成 PitchingBallData virtualPitchingBallData = new PitchingBallData() { IsFastBall = false, PitchingCourse = PitchingCourse.Severe }; // 時間を取得 return GetStealTime(baseNumber, gameData, virtualPitchingBallData); }
/// <summary> /// 盗塁判断結果を返す /// </summary> /// <param name="gameData">試合のデータ</param> /// <returns>判断結果(そもそも盗塁不可なら空文字)</returns> public static string GetSetalJudgeString(GameData gameData) { StealJudgeType stealJudgeType = GetStealJudgeType(gameData); // 盗塁対象外 if (stealJudgeType == StealJudgeType.Invalid) { return string.Empty; } switch (stealJudgeType) { case StealJudgeType.Success: return "(成功確実)"; case StealJudgeType.SuccessIfFastBoll: return "(たぶん成功)"; case StealJudgeType.SuccessIfBreakingBoll: return "(50%成功)"; case StealJudgeType.Impossible: return "(無理)"; default: throw new Exception("Invalid StealJudgeType"); } }
/// <summary> /// 投手に要求する投球データを取得する /// </summary> /// <param name="gameData"></param> /// <param name="requestBall"></param> /// <returns></returns> public PitchingBallData GetRequestBall(GameData gameData, PitchingBallData requestBall) { // 作戦ごとに球種とコースを設定 switch(PitchingMissionKind) { case PitchingMissionKind.Random: // ランダム // 甘いコース、厳しいコース、わずかにボールをランダムに投球 // (ストライク先行とくらべて球数があまり変わらないようにボール球を少し多めにする) int randomValue = RandomCreater.GetPercentValue(); if (randomValue < 30) { requestBall.PitchingCourse = PitchingCourse.Sweet; } else if (randomValue < 60) { requestBall.PitchingCourse = PitchingCourse.Severe; } else { requestBall.PitchingCourse = PitchingCourse.ScantBall; } break; case PitchingMissionKind.StrikeFirst: // ストライク先行 #region ストライク先行 { // ストライクが先行している場合のみボールを投げる int strikeValue; if (gameData.StrikeCount + gameData.BallCount == 0) { // 初球はストライク strikeValue = 75; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 0) { // 2球目:ストライク先行ならボール strikeValue = 25; } else if (gameData.StrikeCount == 0 && gameData.BallCount == 1) { // 2球目:ボール先行ならストライクをかなり優先 strikeValue = 90; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 1) { // 3球目:並行カウントならストライク strikeValue = 75; } else if (gameData.StrikeCount == 2 && gameData.BallCount == 0) { // 3球目:ストライクが2つ先行していればストライクは不要 // (失投でストライクになるため「待て」すればいいというわけではない) strikeValue = 0; } else if (gameData.BallCount >= 2) { // 3球目以降:2ボール以上であればストライクを投げる strikeValue = 100; } else if (gameData.StrikeCount == 2 && gameData.BallCount == 1) { // 4球目:ストライクが1つ先行していればボールをかなり優先 strikeValue = 10; } else { throw new Exception("Invalid Count"); } // 指定した確率でストライクを投球するか判定 if (RandomCreater.GetPercentValue() < strikeValue) { requestBall.PitchingCourse = PitchingCourse.Severe; } else { requestBall.PitchingCourse = PitchingCourse.ScantBall; } } #endregion break; case PitchingMissionKind.UtilizeBall: case PitchingMissionKind.UtilizeBallByUser: // ボールを有効活用 if (PitchingMissionKind == PitchingMissionKind.UtilizeBall && gameData.IsScoringPosition == false) { // 体力温存のため得点圏の場合のみ適用 // (デバッグ用の場合は常に実行する) break; } #region ボールを有効活用 // 並行カウントか2ボールでなければボールを投球 { int strikeValue; if (gameData.StrikeCount + gameData.BallCount == 0) { // 初球はボール strikeValue = 25; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 0) { // 2球目:ストライク先行ならボールをかなり優先 strikeValue = 10; } else if (gameData.StrikeCount == 0 && gameData.BallCount == 1) { // 2球目:ボール先行ならストライク strikeValue = 75; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 1) { // 3球目:並行カウントならボール strikeValue = 25; } else if (gameData.StrikeCount == 2 && gameData.BallCount == 0) { // 3球目:ストライクが2つ先行していればストライクは不要 // (失投でストライクになるため「待て」すればいいというわけではない) strikeValue = 0; } else if (gameData.StrikeCount < 2 && gameData.BallCount >= 2) { // 3球目以降:2ストライクでなく、2ボール以上であればストライクを投げる strikeValue = 100; } else if (gameData.StrikeCount == 2 && gameData.BallCount == 1) { // 4球目:ストライクが1つ先行していればストライク不要 strikeValue = 0; } else if (gameData.StrikeCount == 2 && gameData.BallCount == 2) { // 5球目:2ストライクで2ボールであればボール球を振らせる確率にかけて多少ボールも投げる strikeValue = 100; } else if (gameData.BallCount == 3) { // 3ボールは無条件でストライク strikeValue = 100; } else { throw new Exception("Invalid Count"); } // 指定した確率でストライクを投球するか判定 if (RandomCreater.GetPercentValue() < strikeValue) { requestBall.PitchingCourse = PitchingCourse.Severe; } else { requestBall.PitchingCourse = PitchingCourse.ScantBall; } } #endregion break; case PitchingMissionKind.UtilizePitchOut: // ウエストを有効活用 #region ウエストを活用 // ランナーがいる場合のみ適用 if (gameData.AllRunnerMembers.Count > 0) { // 盗塁対策 // 事実としての判断タイプと、ランナーの判断タイプをもとに判定する RunnerTactics.StealJudgeType realJudgeType = RunnerTactics.GetRealStealJudgeType(gameData); RunnerTactics.StealJudgeType runnerJudgeType = RunnerTactics.GetStealJudgeType(gameData); int pitchOutValue = 0; switch (runnerJudgeType) { case RunnerTactics.StealJudgeType.Invalid: case RunnerTactics.StealJudgeType.Impossible: // 盗塁不可であれば何もしない break; case RunnerTactics.StealJudgeType.SuccessIfBreakingBoll: // 変化球で盗塁可能であれば小確率でウエストする // 実際が常に成功であればウエストしない // (ランナー側も盗塁しなける確率は低いため強制ストライクにしない) // また、実際の判定も「変化球なら成功」ならウエストの必要なし if (realJudgeType == RunnerTactics.StealJudgeType.Success || realJudgeType == RunnerTactics.StealJudgeType.SuccessIfBreakingBoll) { break; } // 以下、実際の判定が「直球なら成功」の場合 // 2アウトでランナー一塁のみ以外であれば、そもそも盗塁してこないので // その条件以外はウエストしない if (gameData.OutCount < 2 || gameData.FirstRunnerMember == null || gameData.SecondRunnerMember != null || gameData.ThirdRunnerMember != null) { break; } if (gameData.StrikeCount + gameData.BallCount == 0) { // 初球はそれなりに警戒 pitchOutValue = 20; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 0) { // 2球目もそれなりに警戒 pitchOutValue = 20; } else if (gameData.StrikeCount == 0 && gameData.BallCount == 1) { // 2球目もそれなりに警戒(ボール先行は不利になるため確率少ない) pitchOutValue = 10; } // 3球目以降は盗塁してこないと判断してウエストしない // 指定した確率でウエストを実行するか判定 if (RandomCreater.GetPercentValue() < pitchOutValue) { requestBall.PitchingCourse = PitchingCourse.PitchOut; } break; case RunnerTactics.StealJudgeType.SuccessIfFastBoll: // 直球で盗塁可能であれば高確率でウエストする if (realJudgeType == RunnerTactics.StealJudgeType.Success) { // 実際が常に成功であれば盗塁される間にカウント稼ぐためにストライクを投げる requestBall.PitchingCourse = PitchingCourse.Severe; break; } // 以下、実際の判定も「直球なら成功」の場合 if (gameData.StrikeCount + gameData.BallCount == 0) { // 初球はかなり警戒 pitchOutValue = 33; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 0) { // 2球目(ストライク先行)もかなり警戒 pitchOutValue = 25; } else if (gameData.StrikeCount == 0 && gameData.BallCount == 1) { // 2球目(ボール先行)もかなり警戒 pitchOutValue = 20; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 1) { // 3球目の並行カウントはそれなりに警戒 pitchOutValue = 15; } else if (gameData.StrikeCount == 2 && requestBall.IsStrike == false) { // 追い込んでいればほとんど盗塁しないと判定 // ただしどうせボール球を投げる予定であれば一定確率でウエストする pitchOutValue = 10; } else if (gameData.BallCount >= 2) { // ボール先行し過ぎると不利なため2ボール以降はウエストしない pitchOutValue = 0; } // 三盗は慎重に行われるため、半分の確率とする if (gameData.StealTargetRunnerNumber == 2) { pitchOutValue /= 2; } // 指定した確率でウエストを実行するか判定 if (RandomCreater.GetPercentValue() < pitchOutValue) { requestBall.PitchingCourse = PitchingCourse.PitchOut; } else if (gameData.StrikeCount <= 1 && gameData.BallCount <= 1) { // 1~3球目でウエストしない場合、カウントを悪くしないために // もともとボール球を指定していてもストライクに変更する requestBall.PitchingCourse = PitchingCourse.Severe; } break; case RunnerTactics.StealJudgeType.Success: // 常に成功であれば100%盗塁されるため // 確実にカウント稼ぐために甘いコースに投げる requestBall.PitchingCourse = PitchingCourse.Sweet; break; } // スクイズ対策 // (盗塁とスクイズの両方警戒の場合、スクイズの警戒で上書きする) if (gameData.UnableSqueeze) { break; } if (gameData.StrikeCount + gameData.BallCount == 0) { // 初球はかなり警戒 pitchOutValue = 33; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 0) { // 2球目(ストライク先行)もかなり警戒 pitchOutValue = 33; } else if (gameData.StrikeCount == 0 && gameData.BallCount == 1) { // 2球目(ボール先行)もかなり警戒 pitchOutValue = 25; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 1) { // 3球目の並行カウントはそれなりに警戒 pitchOutValue = 20; } else if (gameData.StrikeCount == 2) { // 追い込んでいればスクイズしないと判断 pitchOutValue = 0; } else if (gameData.BallCount >= 2) { // ボール先行し過ぎると不利なため2ボール以降はウエストしない pitchOutValue = 0; } // 指定した確率でウエストを実行するか判定 if (RandomCreater.GetPercentValue() < pitchOutValue) { requestBall.PitchingCourse = PitchingCourse.PitchOut; } else if (gameData.StrikeCount <= 1 && gameData.BallCount <= 1) { // 1~3球目でウエストしない場合、カウントを悪くしないために // もともとボール球を指定していてもストライクに変更する requestBall.PitchingCourse = PitchingCourse.Severe; } } break; #endregion case PitchingMissionKind.SavingPower: // 格下には省エネ // 以下の条件をすべて満たす場合に適用 // ・序盤で同点以上か、中盤以降で2点差以上で勝っている // ・1アウトか2アウト // ・ランナー無し // ・打者能力が格下(すべてストライク狙いで選球眼の寄与率が低いため打者能力はミート&パワーとする) if (((gameData.CurrentInning <= 3 && gameData.RunScoreDeltaForAttackTeam <= 0) || gameData.RunScoreDeltaForAttackTeam <= -2) && gameData.OutCount > 0 && gameData.AllRunnerMembers.Count == 0 && gameData.CurrentPitcherAbirity.PitcherTotalConsideringStamina - gameData.CurrentBatterAbirity.MeetAndPower > Constants.DeltaAbilityForSavingPower) { // 厳しいコースのみを投げる requestBall.PitchingCourse = PitchingCourse.Severe; } break; case PitchingMissionKind.AvoidFourBall: // 3ボールなら甘いコース // 3ボールでランナー無しか一塁ランナーがいる場合は甘いコース // (一塁が空いていればランナー出しても構わないため甘いコースにしない) if (gameData.BallCount == 3 && (gameData.AllRunnerMembers.Count == 0 || gameData.FirstRunnerMember != null)) { requestBall.PitchingCourse = PitchingCourse.Sweet; } break; case PitchingMissionKind.StrongBall: // 得意な球種を多用 { // 能力差1につき4%を補正(13以上の差がある場合は1球種のみとなる) double fastValue = gameData.CurrentPitcherAbirity.Fastball; double breakingValue = gameData.CurrentPitcherAbirity.Breakingball; double delta = fastValue - breakingValue; double percent = 50 + delta * 4; requestBall.IsFastBall = RandomCreater.GetPercentValue() < percent; } break; case PitchingMissionKind.StrongBallByChangeBollKind: // 球種変更補正を含めた強い球種を多用 { // 球種変更補正を含めたときに、能力差1につき6%を補正 //(1差で6%、9差以上で100%確定) double originFastBall = gameData.CurrentPitcherAbirity.Fastball; double originBreakingBall = gameData.CurrentPitcherAbirity.Breakingball; double fastValue = originFastBall + GameManager.GetOffsetValueByChabgeBollKind(gameData, true); double breakingValue = originBreakingBall + GameManager.GetOffsetValueByChabgeBollKind(gameData, false); double delta = fastValue - breakingValue; double percent = 50 + delta * 6; requestBall.IsFastBall = RandomCreater.GetPercentValue() < percent; // 同じ球種を続けて投げている場合、元々弱い球種が強い球種を超えた場合は // 補正を受けるために必ず球種を切り替える // (ただしストライクの場合。ボールの時に補正の効いた球を投げるのはもったいないため) if (gameData.ContinueingSameBollCount >= 3 && PitchingCourseHelper.IsStrike(requestBall.PitchingCourse)) { if ((originFastBall < originBreakingBall && fastValue > breakingValue)) { requestBall.IsFastBall = true; } else if (originFastBall > originBreakingBall && fastValue < breakingValue) { requestBall.IsFastBall = false; } } } break; case PitchingMissionKind.AllSevere: // 常に厳しいコース requestBall.PitchingCourse = PitchingCourse.Severe; break; default: throw new Exception("Invalid PitchingMissionKind"); } // デバッグ用(直球確率がデバッグ用に変更されている場合はその確率に従って投げる) if (Constants.FastBallPercent != 50) { requestBall.IsFastBall = RandomCreater.GetPercentValue() < Constants.FastBallPercent; } return requestBall; }
/// <summary> /// 現在の投手としての補正値を文字列として返す /// </summary> /// <param name="GameData">試合のデータ</param> public string GetCurrentPitcherOffsetInfo(GameData GameData) { StringBuilder builder = new StringBuilder(); // リリーフ if (IsRelief) { builder.AppendLine(string.Format("リリーフで直球・変化球・制球+{0}、体力消耗のダウンなし", Constants.ReliefOffset)); } // 体力低下 if (IsDownValueByRemainingStamina) { // 能力低下分の体力=最大体力 - 残り体力 - 能力低下開始する体力値 double downStaminaPoint = MaxStamina - RemainingStamina - (int)(MaxStamina * Constants.AbilityDownStamina); // ダウン比率を表示 int downRasio = (int)Math.Ceiling(100 * downStaminaPoint / MaxStamina); builder.AppendLine(string.Format("体力消耗で直球・変化球・制球{0}%ダウン", downRasio)); } #region 特殊能力補正 // 奪三振 // 2ストライクの場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.GetStrikeOut && GameData.StrikeCount == 2) { builder.AppendLine("特殊能力で直球・変化球が+1"); } // 逆境○ // 7回以降に負けている場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.Adversity && GameData.CurrentInning >= 7 && GameData.RunScoreDeltaForAttackTeam > 0) { builder.AppendLine("特殊能力で直球・変化球が+2"); } // 最終回○ // 9回の場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.LastIninng && GameData.CurrentInning == 9) { builder.AppendLine("特殊能力で直球・変化球が+2"); } // ピンチ○ // 得点圏の場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.Pinch && GameData.IsScoringPosition) { builder.AppendLine("特殊能力で制球が+1"); } // 3ボール○ // 3ボールの場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.ThreeBoll && GameData.BallCount == 3) { builder.AppendLine("特殊能力で制球が+2"); } // 三塁ランナー○ // 三塁ランナーがいる場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.ThirdRunner && GameData.ThirdRunnerMember != null) { builder.AppendLine("特殊能力で制球が+2"); } // フルカウント○ // フルカウントの場合に能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.FullCount && GameData.BallCount == 3 && GameData.StrikeCount == 2) { builder.AppendLine("特殊能力で制球が+4"); } // 決勝戦○ // 決勝戦であれば能力アップ if (Player.PitcherAbility.SpecialPitcherAbility == SpecialPitcherAbility.FinalMatch && EVManager.Instance.IsFinalGame) { builder.AppendLine("特殊能力で直球・変化球が+2"); } #endregion // 前回投げた球種による補正 if (GameData.ContinueingSameBollCount > 0) { if (GameData.PreviousBollKind) { // 直球の場合 if (GameData.ContinueingSameBollCount == 1) { builder.AppendLine(string.Format("直前が直球のため直球-{0}", GameManager.GetOffsetValueByChabgeBollKind(GameData, true) * (-1))); } else { builder.AppendLine(string.Format("連続{0}球の直球のため直球-{1}、変化球+{2}", GameData.ContinueingSameBollCount, GameManager.GetOffsetValueByChabgeBollKind(GameData, true) * (-1), GameManager.GetOffsetValueByChabgeBollKind(GameData, false))); } } else { // 変化球の場合 if (GameData.ContinueingSameBollCount == 1) { builder.AppendLine(string.Format("直前が変化球のため変化球-{0}", GameManager.GetOffsetValueByChabgeBollKind(GameData, false) * (-1))); } else { builder.AppendLine(string.Format("連続{0}球の変化球のため変化球-{1}、直球+{2}", GameData.ContinueingSameBollCount, GameManager.GetOffsetValueByChabgeBollKind(GameData, false) * (-1), GameManager.GetOffsetValueByChabgeBollKind(GameData, true))); } } } return builder.ToString(); }
/// <summary> /// 現在の打者としての補正値を文字列として返す /// </summary> /// <param name="GameData">試合のデータ</param> public string GetCurrentBatterOffsetInfo(GameData GameData) { StringBuilder builder = new StringBuilder(); // 代打補正 if (IsPinchHitter) { builder.AppendLine(string.Format("代打でミート・智力が+{0}", Constants.PinchHitterOffset)); } // 左右補正 if (Player.IsLeftBox) { if (GameData.CurrentPitcher.Player.IsLeftThrow) { // 左対左ならマイナス補正 builder.AppendLine(string.Format("左対左でミート・パワーが-{0}", Constants.LeftBoxOffset)); } else { // 右対左ならプラス補正 builder.AppendLine(string.Format("右対左でミート・パワーが+{0}", Constants.LeftBoxOffset)); } } #region 特殊能力補正 // プルヒッター if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.PullHitter) { builder.AppendLine("特殊能力でベース際に引っ張る打球が多い"); } // 流し打ち if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.HitTheOtherWay) { builder.AppendLine("特殊能力で強い打球で流し打ちができる"); } // 連打○ // 前の打者が安打を打っている場合に能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.ConsecutionHit && GameData.IsHitAtLatestBatter) { builder.AppendLine("特殊能力でミートが+1"); } // 先頭打者○ // 先頭打者の場合に能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.FirstBatter && GameData.IsFirstBatter) { builder.AppendLine("特殊能力でミートが+1"); } // チャンス○ // 二塁か三塁にランナーがいる場合に能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.Chance && (GameData.SecondRunnerMember != null || GameData.ThirdRunnerMember != null)) { builder.AppendLine("特殊能力でミートが+1"); } // 2ストライク○ // 2ストライクの場合に能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.TwoStrikeMan && GameData.StrikeCount == 2) { builder.AppendLine("特殊能力でパワーが+2"); } // 逆境○ // 7回以降で負けている場合に能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.Adversity && GameData.CurrentInning >= 7 && GameData.RunScoreDeltaForAttackTeam < 0) { builder.AppendLine("特殊能力でパワーが+2"); } // 決勝点男 // 負けているか同点の場合に得点圏のランナーを返して決勝点になる場合に能力アップ // (同点で二塁か三塁か、1点差負けで二三塁の場合) if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.DecisiveRunMan && ((GameData.RunScoreDeltaForAttackTeam == 0 && (GameData.SecondRunnerMember != null || GameData.ThirdRunnerMember != null)) || GameData.RunScoreDeltaForAttackTeam == -1 && GameData.SecondRunnerMember != null && GameData.ThirdRunnerMember != null)) { builder.AppendLine("特殊能力でミートが+3"); } // サヨナラ男 // 9回以降の裏の攻撃で、本塁打でサヨナラにできる状態であれば能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.GoodByMan && GameData.CurrentInning >= 9 && !GameData.IsCurrentInningTop && GameData.AllRunnerMembers.Count + 1 - GameData.RunScoreDeltaForAttackTeam > 0) { builder.AppendLine("特殊能力でパワーが+4"); } // 決勝戦○ // 決勝戦であれば能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.FinalMatch && EVManager.Instance.IsFinalGame) { builder.AppendLine("特殊能力でパワーが+4"); } // 満塁男 // 満塁の場合に能力アップ if (Player.FielderAbility.SpecialFilederAbility == SpecialFilederAbility.FullBaseMan && GameData.AllRunnerMembers.Count == 3) { builder.AppendLine("特殊能力でミートが+6"); } #endregion return builder.ToString(); }
/// <summary> /// UI更新 /// </summary> /// <param name="gameData"></param> public void UpdateControl(GameData gameData) { GameData GameData = gameData; // アウトカウント if (GameData.OutCount == 0) { OutCount1.Visibility = Visibility.Collapsed; OutCount2.Visibility = Visibility.Collapsed; ChangeText.Visibility = Visibility.Collapsed; } else if (GameData.OutCount == 1) { OutCount1.Visibility = Visibility.Visible; OutCount2.Visibility = Visibility.Collapsed; ChangeText.Visibility = Visibility.Collapsed; } else if (GameData.OutCount == 2) { OutCount1.Visibility = Visibility.Visible; OutCount2.Visibility = Visibility.Visible; ChangeText.Visibility = Visibility.Collapsed; } else if (GameData.OutCount == 3) { OutCount1.Visibility = Visibility.Visible; OutCount2.Visibility = Visibility.Visible; ChangeText.Visibility = Visibility.Visible; } // 野手 Defense1.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Pitcher).GameMember.Player.BreedType); Defense2.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Catcher).GameMember.Player.BreedType); Defense3.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.First).GameMember.Player.BreedType); Defense4.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Second).GameMember.Player.BreedType); Defense5.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Third).GameMember.Player.BreedType); Defense6.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Short).GameMember.Player.BreedType); Defense7.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Left).GameMember.Player.BreedType); Defense8.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Center).GameMember.Player.BreedType); Defense9.Source = UIUtility.GetPlayerImage(GameData.GetDefenseMemberAbility(DefensePosition.Right).GameMember.Player.BreedType); Defense1.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Pitcher).GameMember.Player.IsLeftThrow); Defense2.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Catcher).GameMember.Player.IsLeftThrow); Defense3.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.First).GameMember.Player.IsLeftThrow); Defense4.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Second).GameMember.Player.IsLeftThrow); Defense5.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Third).GameMember.Player.IsLeftThrow); Defense6.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Short).GameMember.Player.IsLeftThrow); Defense7.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Left).GameMember.Player.IsLeftThrow); Defense8.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Center).GameMember.Player.IsLeftThrow); Defense9.RenderTransform = UIUtility.GetPlayerImageRenderTransform(GameData.GetDefenseMemberAbility(DefensePosition.Right).GameMember.Player.IsLeftThrow); // ランナー位置(バッター表示は無し) if (GameData.FirstRunnerMember != null) { Runner1.Source = UIUtility.GetPlayerImage(GameData.FirstRunnerMember.Player.BreedType); Runner1.Visibility = Visibility.Visible; } else { Runner1.Visibility = Visibility.Collapsed; } if (GameData.SecondRunnerMember != null) { Runner2.Source = UIUtility.GetPlayerImage(GameData.SecondRunnerMember.Player.BreedType); Runner2.Visibility = Visibility.Visible; } else { Runner2.Visibility = Visibility.Collapsed; } if (GameData.ThirdRunnerMember != null) { Runner3.Source = UIUtility.GetPlayerImage(GameData.ThirdRunnerMember.Player.BreedType); Runner3.Visibility = Visibility.Visible; } else { Runner3.Visibility = Visibility.Collapsed; } }
/// <summary> /// ランナーの盗塁判断タイプを取得する /// </summary> /// <param name="gameData">試合のデータ</param> /// <returns>盗塁判断タイプ</returns> public static StealJudgeType GetStealJudgeType(GameData gameData) { StealJudgeType stealJudgeType = StealJudgeType.Invalid; // ランナーがいないか満塁の場合は何もしない if (gameData.AllRunnerMembers.Count == 0 || gameData.AllRunnerMembers.Count == 3) { return stealJudgeType; } // 盗塁対象外ならそれを返す int baseNumber = gameData.StealTargetRunnerNumber; if (baseNumber == 0) { return stealJudgeType; } // 対象ランナーの盗塁判定 TryStealPerRunner(baseNumber, gameData, out stealJudgeType); return stealJudgeType; }
/// <summary> /// UI更新 /// </summary> /// <param name="gameData"></param> public void Update(GameData gameData) { Update(gameData, true); }
/// <summary> /// 盗塁で次の塁までにかかる時間を取得する(ウエスト) /// </summary> /// <param name="baseNumber">盗塁するランナーのベース番号</param> /// <param name="gameData">試合のデータ</param> /// <returns>盗塁で次の塁までにかかる時間</returns> public static int GetStealTimeByPitchOut(int baseNumber, GameData gameData) { // 想定する投球データを作成 PitchingBallData virtualPitchingBallData = new PitchingBallData() { IsFastBall = true, PitchingCourse = PitchingCourse.PitchOut }; // 時間を取得 return GetStealTime(baseNumber, gameData, virtualPitchingBallData); }
/// <summary> /// UI更新 /// </summary> /// <param name="gameData"></param> /// <param name="extend">延長表示するか(falseの場合は延長表示しない)</param> public void Update(GameData gameData, bool extend) { Assertion.Assert(gameData.CurrentInning <= Constants.ExtensionLastInning, "gameData.CurrentInning <= Constants.ExtensionLastInning"); // 表示するイニング数(表と裏で別カウント)をカウントする int showCount = (gameData.CurrentInning - 1) * 2 + (gameData.IsCurrentInningTop ? 0 : 1); if ((gameData.IsCurrentInningTop && gameData.TopTeamRunScorePerInning[gameData.CurrentInning - 1] > 0) || (!gameData.IsCurrentInningTop && gameData.BottomTeamRunScorePerInning[gameData.CurrentInning - 1] > 0) || gameData.IsEnd) { // 現在攻撃中のイニングですでに得点が入っている場合か試合終了時はそのイニングの得点も表示 showCount++; } if (gameData.IsEnd && gameData.TopTeamRunScore < gameData.BottomTeamRunScore && gameData.CurrentInning == 9 && gameData.IsCurrentInningTop) { // 試合終了時、後攻チームが勝利し、9回表の場合、9回裏のスコアに×を表示 Score2_9.Text = "×"; } if (gameData.CurrentInning <= 10 || !extend) { if (showCount >= 1) Score1_1.Text = gameData.TopTeamRunScorePerInning[0].ToString(); if (showCount >= 3) Score1_2.Text = gameData.TopTeamRunScorePerInning[1].ToString(); if (showCount >= 5) Score1_3.Text = gameData.TopTeamRunScorePerInning[2].ToString(); if (showCount >= 7) Score1_4.Text = gameData.TopTeamRunScorePerInning[3].ToString(); if (showCount >= 9) Score1_5.Text = gameData.TopTeamRunScorePerInning[4].ToString(); if (showCount >= 11) Score1_6.Text = gameData.TopTeamRunScorePerInning[5].ToString(); if (showCount >= 13) Score1_7.Text = gameData.TopTeamRunScorePerInning[6].ToString(); if (showCount >= 15) Score1_8.Text = gameData.TopTeamRunScorePerInning[7].ToString(); if (showCount >= 17) Score1_9.Text = gameData.TopTeamRunScorePerInning[8].ToString(); if (showCount >= 19) Score1_10.Text = gameData.TopTeamRunScorePerInning[9].ToString(); if (showCount >= 2) Score2_1.Text = gameData.BottomTeamRunScorePerInning[0].ToString(); if (showCount >= 4) Score2_2.Text = gameData.BottomTeamRunScorePerInning[1].ToString(); if (showCount >= 6) Score2_3.Text = gameData.BottomTeamRunScorePerInning[2].ToString(); if (showCount >= 8) Score2_4.Text = gameData.BottomTeamRunScorePerInning[3].ToString(); if (showCount >= 10) Score2_5.Text = gameData.BottomTeamRunScorePerInning[4].ToString(); if (showCount >= 12) Score2_6.Text = gameData.BottomTeamRunScorePerInning[5].ToString(); if (showCount >= 14) Score2_7.Text = gameData.BottomTeamRunScorePerInning[6].ToString(); if (showCount >= 16) Score2_8.Text = gameData.BottomTeamRunScorePerInning[7].ToString(); if (showCount >= 18) Score2_9.Text = gameData.BottomTeamRunScorePerInning[8].ToString(); if (showCount >= 20) Score2_10.Text = gameData.BottomTeamRunScorePerInning[9].ToString(); } else { // 延長11回以降の場合 Ininng1.Text = "11"; Ininng2.Text = "12"; Ininng3.Text = "13"; Ininng4.Text = "14"; Ininng5.Text = "15"; Ininng6.Text = string.Empty; Ininng7.Text = string.Empty; Ininng8.Text = string.Empty; Ininng9.Text = string.Empty; Ininng10.Text = string.Empty; Score1_1.Text = string.Empty; Score1_2.Text = string.Empty; Score1_3.Text = string.Empty; Score1_4.Text = string.Empty; Score1_5.Text = string.Empty; Score1_6.Text = string.Empty; Score1_7.Text = string.Empty; Score1_8.Text = string.Empty; Score1_9.Text = string.Empty; Score1_10.Text = string.Empty; Score2_1.Text = string.Empty; Score2_2.Text = string.Empty; Score2_3.Text = string.Empty; Score2_4.Text = string.Empty; Score2_5.Text = string.Empty; Score2_6.Text = string.Empty; Score2_7.Text = string.Empty; Score2_8.Text = string.Empty; Score2_9.Text = string.Empty; Score2_10.Text = string.Empty; if (showCount >= 21) Score1_1.Text = gameData.TopTeamRunScorePerInning[10].ToString(); if (showCount >= 23) Score1_2.Text = gameData.TopTeamRunScorePerInning[11].ToString(); if (showCount >= 25) Score1_3.Text = gameData.TopTeamRunScorePerInning[12].ToString(); if (showCount >= 27) Score1_4.Text = gameData.TopTeamRunScorePerInning[13].ToString(); if (showCount >= 29) Score1_5.Text = gameData.TopTeamRunScorePerInning[14].ToString(); if (showCount >= 22) Score2_1.Text = gameData.BottomTeamRunScorePerInning[10].ToString(); if (showCount >= 24) Score2_2.Text = gameData.BottomTeamRunScorePerInning[11].ToString(); if (showCount >= 26) Score2_3.Text = gameData.BottomTeamRunScorePerInning[12].ToString(); if (showCount >= 28) Score2_4.Text = gameData.BottomTeamRunScorePerInning[13].ToString(); if (showCount >= 30) Score2_5.Text = gameData.BottomTeamRunScorePerInning[14].ToString(); } // 得点・ヒット・エラーの更新 if (gameData.CurrentInning > 10 && !extend) { // 延長表示なしで、延長がある場合、得点・ヒット・エラーは表示しない Score1_R.Text = string.Empty; Score2_R.Text = string.Empty; Score1_H.Text = string.Empty; Score2_H.Text = string.Empty; Score1_E.Text = string.Empty; Score2_E.Text = string.Empty; Score_R.Text = string.Empty; Score_H.Text = string.Empty; Score_E.Text = string.Empty; } else { // そうでなければ表示更新 Score1_R.Text = gameData.TopTeamRunScore.ToString(); Score2_R.Text = gameData.BottomTeamRunScore.ToString(); Score1_H.Text = gameData.TopTeamSetting.HitCount.ToString(); Score2_H.Text = gameData.BottomTeamSetting.HitCount.ToString(); Score1_E.Text = gameData.TopTeamSetting.ErrorCount.ToString(); Score2_E.Text = gameData.BottomTeamSetting.ErrorCount.ToString(); } }
/// <summary> /// 盗塁で次の塁までにかかる時間を取得する /// </summary> /// <param name="baseNumber">盗塁するランナーのベース番号</param> /// <param name="gameData">試合のデータ</param> /// <param name="pitchingBallData">想定する投球データ</param> /// <returns>盗塁で次の塁までにかかる時間</returns> private static int GetStealTime(int baseNumber, GameData gameData, PitchingBallData pitchingBallData) { // リード距離の取得 double leadDistance = GetLeadDistance(baseNumber, true, gameData, pitchingBallData); // 次の塁までの残り距離の取得 double remainingDistance = Constants.BaseDistance - leadDistance; // 次の塁に到達するまでの時間を取得 GameMemberAbility memberAbility = GetRunnerAbility(baseNumber, gameData); int remainingTime = (int)Math.Ceiling(remainingDistance / (memberAbility.RunSpeed)); // 時間を返す return remainingTime; }
/// <summary> /// コンストラクタ /// </summary> /// <param name="member">メンバ</param> /// <param name="gameData">試合データ</param> public GameMemberAbility(GameMember member, GameData gameData) { GameMember = member; GameData = gameData; }
/// <summary> /// リード距離を算出する /// </summary> /// <param name="baseNumber">元の塁の番号(1~3)</param> /// <param name="isStealRunner">盗塁するランナーか</param> /// <param name="gameData">試合のデータ</param> /// <param name="pitchingBallData">投球データ</param> /// <returns>リード距離</returns> public static double GetLeadDistance(int baseNumber, bool isStealRunner, GameData gameData, PitchingBallData pitchingBallData) { // メンバ能力の取得 GameMemberAbility memberAbility = GetRunnerAbility(baseNumber, gameData); // 通常のリード距離を算出 // (最小リード距離+智力依存のリード距離) double leadDistance = Constants.MinRunnerLeadDistance; { // 智力Sでそのままリード距離を算出すると、走力が低くても簡単に盗塁できてしまうため // 最大リード距離の1.5倍までをリード距離の制限とする double normalDistance = Math.Min( GameMemberAbility.GetHigherValueOverBaseline(memberAbility.Wisdom, Constants.MaxRunnerLeadDistance), Constants.MaxRunnerLeadDistance * 1.5); leadDistance += normalDistance; } // 2アウトの場合はフライアウトで戻る必要がない分、余分にリードする(智力依存) if (gameData.OutCount == 2 && !isStealRunner) { leadDistance += GameMemberAbility.GetHigherValueOverBaseline(memberAbility.Wisdom, Constants.TwoOutRunnerAdditionalLeadDistance); } // 二塁ランナーはベースカバーが離れているため余分にリードできる(智力依存) if (baseNumber == 2) { // 智力Sでも最大距離以上はリードできない制限を付ける(三盗が簡単にできてしまうようになるため) double secondDistance = GameMemberAbility.GetHigherValueOverBaseline(memberAbility.Wisdom, Constants.SecondRunnerAdditionalLeadDistance); leadDistance += Math.Min(secondDistance, Constants.SecondRunnerAdditionalLeadDistance); } // バントの場合は、ゴロを期待して余分にリードできる(固定) if (gameData.CurrentBattingBunt && !isStealRunner) { leadDistance += Constants.BuntAdditionalLeadDistance; } // 盗塁の場合は余分にリードする(智力依存) if (isStealRunner) { // 盗塁時に余分にリードする距離を加算 // (この値は小さいため、智力Sでの制限は付けない) leadDistance += GameMemberAbility.GetHigherValueOverBaseline(memberAbility.Wisdom, Constants.StealRunnerAdditionalMaxLeadDistance); // ウエストでなければリード距離を加算 // (gameData.LatestPitchingBollResult.PitchingBallDataは予想段階では確定していないため引数の値を利用) if (pitchingBallData.PitchingCourse != PitchingCourse.PitchOut) { // 球種ごとのリード距離加算 if (pitchingBallData.IsFastBall) { // 直球はそれなりにリード距離追加あり leadDistance += Constants.StealRunnerAdditionalLeadSecondByFastBall * memberAbility.RunSpeed; } else { // 変化球は多めにリード距離追加あり leadDistance += Constants.StealRunnerAdditionalLeadSecondByBreakingBall * memberAbility.RunSpeed; } // 打者に対する球数によってリードする距離を加算 // (このメソッドを呼ばれた時点で球数は+1されていることを前提に計算する) // (1球目はリード距離追加なし) if (gameData.ThrowBallCountForSteal >= 2) { // 2球目から加算 leadDistance += Constants.StealRunnerAdditionalLeadSecondByFirstThrow * memberAbility.RunSpeed; // 3球目以降は球数に応じて少しずつ加算 if (gameData.ThrowBallCountForSteal >= 3) { // 4球目以降は同じとする(加算が多くなりすぎるため) int count = Math.Min(gameData.ThrowBallCountForSteal - 1, 4); leadDistance += count * Constants.StealRunnerAdditionalLeadSecondByThrowCount * memberAbility.RunSpeed; } } } else { // ウエストの場合、むしろリード距離を減算する leadDistance -= Constants.StealRunnerMinusLeadSecondByPitchOut * memberAbility.RunSpeed; } } // 智力と走力が高すぎてリード距離がベース間距離を超えてしまう場合はベース間距離に補正する if (leadDistance > Constants.BaseDistance) { leadDistance = Constants.BaseDistance; } return leadDistance; }
/// <summary> /// コンストラクタ /// </summary> /// <param name="gameData"></param> public PitchingMissionManager(GameData gameData) { GameData = gameData; }
/// <summary> /// オーダー設定ボタンハンドラ /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OrderButton_Click(object sender, RoutedEventArgs e) { // デフォルト設定を元にメンバを設定を複製し、それを編集するメンバ設定ビューを表示 UserTeamSetting.CreateCurrentMembersFromDefault(); GameData gameData = new GameData(UserTeamSetting, null, true); m_MemberSelectView.Initialize(gameData.UserTeamSetting, gameData, MemberSelectView.ModeType.OrderSetting); }
/// <summary> /// 初期化処理 /// </summary> /// <param name="teamSetting"></param> /// <param name="gameData"></param> /// <param name="modeType"></param> public void Initialize(TeamSetting teamSetting, GameData gameData, ModeType modeType) { // フィールドの格納 TeamSetting = teamSetting; GameData = gameData; // フィールドの初期化 m_PlayingMembers.Clear(); m_SubMembers.Clear(); m_OutsideMembers.Clear(); m_ChangedMembers.Clear(); m_ChangeSets.Clear(); foreach (GameMember member in TeamSetting.CurrentPlayingMembers) { m_PlayingMembers.Add(member.Clone()); } foreach (GameMember member in TeamSetting.CurrentSubMembers) { m_SubMembers.Add(member.Clone()); } foreach (GameMember member in TeamSetting.CurrentOutSideMembers) { m_OutsideMembers.Add(member.Clone()); } foreach (GameMember member in TeamSetting.CurrentChangedMembers) { m_ChangedMembers.Add(member.Clone()); } // ベンチ外メンバを非表示 SetOutsideMemberVisible(false); // モードごとの個別設定 UpdateControlByModeType(modeType); // 表示状態に変更 this.Visibility = Visibility.Visible; }
/// <summary> /// スイングのデータを取得する /// </summary> /// <param name="ballData"></param> /// <param name="gameData"></param> /// <param name="swingData"></param> /// <returns></returns> public BattingSwingData GetSwingData(PitchingBallData ballData, GameData gameData, BattingSwingData swingData) { // 優先度の低い作戦順に処理して上書きすることを前提とするため // IsSwingとSwingKindの両方を必ずしも設定しない switch (BattingMissionKind) { #region スイングの種別選定 case BattingMissionKind.SwingStrike: // ストライクを振る swingData.IsSwing = PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye); swingData.BattingSwingKind = BattingSwingKind.Normal; break; case BattingMissionKind.RollBallByAbility: // 得意なら転がせ // パワーが一定以下で、ミートがパワーより大幅に高い場合は転がす if (gameData.CurrentBatter.Power < Constants.MinValueForEfficientSwing && gameData.CurrentBatter.Meet - gameData.CurrentBatter.Power >= Constants.DeltaForRollBollByAbility) { swingData.BattingSwingKind = BattingSwingKind.RollBoll; } // 内野前進かバントシフトの場合、転がせ有利のため // パワーが一定未満か[ミート > パワー]なら実行 if ((gameData.InFielderDrawIn || gameData.BuntShift) && (gameData.CurrentBatter.Power < Constants.MinValueForEfficientSwing || gameData.CurrentBatter.Meet > gameData.CurrentBatter.Power)) { swingData.BattingSwingKind = BattingSwingKind.RollBoll; } break; case BattingMissionKind.FullSwingByAbility: // 得意なら長打狙い // 以下の条件を満たす場合に実行 // ・パワーが一定以上 // ・パワーがミート以上 // ・8回までで二死ランナーなしか二死一塁(長打狙いだと打率が大幅に下がるため) if (gameData.CurrentBatter.Power >= Constants.PowerForFullSwingByAbility && gameData.CurrentBatter.Power >= gameData.CurrentBatter.Meet && gameData.CurrentInning <= 8 && gameData.OutCount == 2 && gameData.AllRunnerMembers.Count <= 1 && gameData.SecondRunnerMember == null && gameData.ThirdRunnerMember == null) { swingData.BattingSwingKind = BattingSwingKind.FullSwing; } break; case BattingMissionKind.RightBatting: // 右打ち // 右打者であり、無死二塁で、ミート>パワーの場合、右打ちする // (一死二塁は、右打ちしない方が良い場合もあるため、自動では右打ちしない) if (!gameData.CurrentBatter.Player.IsLeftBox && gameData.OutCount == 0 && gameData.AllRunnerMembers.Count == 1 && gameData.SecondRunnerMember != null && gameData.CurrentBatter.Meet > gameData.CurrentBatter.Power) { swingData.BattingSwingKind = BattingSwingKind.RightBatting; } break; case BattingMissionKind.FullSwingByTwoStrike: // 2ストライクまで長打狙い if (gameData.StrikeCount < 2) { swingData.BattingSwingKind = BattingSwingKind.FullSwing; } break; case BattingMissionKind.NormalSwingByUser: // 通常スイング(ユーザ操作) swingData.BattingSwingKind = BattingSwingKind.Normal; break; case BattingMissionKind.FullSwingByUser: // 長打狙い(ユーザ操作) swingData.BattingSwingKind = BattingSwingKind.FullSwing; break; case BattingMissionKind.RollBallByUser: // 転がせ(ユーザ操作) swingData.BattingSwingKind = BattingSwingKind.RollBoll; // 智力が一定以上の場合、ユーザ戦術が「転がせ」であっても // 右打者であり、無死二塁の場合、右打ちする // (一死二塁は、右打ちしない方が良い場合もあるため、自動では右打ちしない) if (gameData.CurrentBatter.Wisdom >= Constants.WisdomForRightBatting && !gameData.CurrentBatter.Player.IsLeftBox && gameData.OutCount == 0 && gameData.AllRunnerMembers.Count == 1 && gameData.SecondRunnerMember != null) { swingData.BattingSwingKind = BattingSwingKind.RightBatting; } break; #endregion #region 狙い球の選定 case BattingMissionKind.TargetSweetCourseByTwoStrike: // 甘い球狙い(2ストライクまで) if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye) && gameData.StrikeCount < 2) { if (ballData.PitchingCourseByBattingEye == PitchingCourse.Center || ballData.PitchingCourseByBattingEye == PitchingCourse.Sweet) { // ストライクでど真ん中か甘いコースのみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 1; } else { // 狙い球でなければスイングしない swingData.IsSwing = false; } } break; case BattingMissionKind.TargetStrongBall: // 得意球種狙い if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { // 球種能力差が大きい場合に適用 // 能力オール8で球種能力差が4でOPSが大きく上がるため、その差以上で適用 // (得意球種を投げる確率はPitchingMission.GetRequestBallメソッド参照) double fastValue = gameData.CurrentPitcherAbirity.Fastball; double breakingValue = gameData.CurrentPitcherAbirity.Breakingball; double delta = fastValue - breakingValue; if (Math.Abs(delta) >= 4) { // 狙う球種の設定 bool targetFastBall = fastValue > breakingValue; // 相手バッテリーが「得意な球種を多用」作戦の実行ができない智力の場合 // 逆に弱い方の球種を狙う(50%で弱い球種が来るならその方が狙い目) if (gameData.CurrentBatteryWisdom < Constants.WisdomForStrongBoll) { targetFastBall = !targetFastBall; } if (targetFastBall == ballData.IsFastBall) { // ストライクで狙う球種が一致した時のみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 1; } else { if (gameData.StrikeCount < 2) { // 狙う球種が一致しなければスイングしない swingData.IsSwing = false; } else { // 追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } } break; case BattingMissionKind.TargetSweetAndFastOrBreakingBall: // 甘い直球か甘い変化球狙い // 智力が打力より圧倒的に高い場合に適用する(カットするごとにカットのための智力は減衰) if (gameData.CurrentBatter.Wisdom - gameData.FoulCountForSwing * Constants.DownCutAbilityByThrowBall - gameData.CurrentBatter.MeetAndPower >= Constants.TargetFourBollMeetAndPowerDelta) { if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { // 相手投手の能力が高い方の球種に絞って対応する bool targeFastBalll = gameData.CurrentPitcher.Fastball > gameData.CurrentPitcher.Breakingball; // 相手バッテリーが「得意な球種を多用」作戦の実行ができない智力の場合 // 逆に弱い方の球種を狙う(50%で弱い球種が来るならその方が狙い目) if (gameData.CurrentBatteryWisdom < Constants.WisdomForStrongBoll) { targeFastBalll = !targeFastBalll; } if ((ballData.PitchingCourseByBattingEye == PitchingCourse.Center || ballData.PitchingCourseByBattingEye == PitchingCourse.Sweet) && ballData.IsFastBall == targeFastBalll) { // ど真ん中か甘いコースで球種が一致時のみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 2; } else { if (gameData.StrikeCount < 2) { // 条件に合わなければスイングしない swingData.IsSwing = false; } else { // 追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } } break; case BattingMissionKind.TargetFastBallByUser: // 直球狙い(ユーザ操作) if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { if (ballData.IsFastBall) { // ストライクで直球のときのみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 1; } else { if (gameData.StrikeCount< 2) { // 変化球はスイングしない swingData.IsSwing = false; } else { // 変化球でも追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } break; case BattingMissionKind.TargetBreakingBallByUser: // 変化球狙い(ユーザ操作) if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { if (!ballData.IsFastBall) { // ストライクで変化球のときのみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 1; } else { if (gameData.StrikeCount < 2) { // 直球はスイングしない swingData.IsSwing = false; } else { // 直球でも追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } break; case BattingMissionKind.TargetSweetCourseByUser: // 甘い球狙い(ユーザ操作) if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { if (ballData.PitchingCourseByBattingEye == PitchingCourse.Center || ballData.PitchingCourseByBattingEye == PitchingCourse.Sweet) { // ストライクでど真ん中か甘いコースのみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 1; } else { if (gameData.StrikeCount < 2) { // 甘いコースでなければスイングしない swingData.IsSwing = false; } else { // 甘いコースでなくても、追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } break; case BattingMissionKind.TargetSweetFastBallByUser: // 甘い直球狙い(ユーザ操作) if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { if ((ballData.PitchingCourseByBattingEye == PitchingCourse.Center || ballData.PitchingCourseByBattingEye == PitchingCourse.Sweet) && ballData.IsFastBall) { // ど真ん中か甘いコースで直球のみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 2; } else { if (gameData.StrikeCount < 2) { // 条件に合わなければスイングしない swingData.IsSwing = false; } else { // 追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } break; case BattingMissionKind.TargetSweetBreakingBallByUser: // 甘い変化球狙い(ユーザ操作) if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { if ((ballData.PitchingCourseByBattingEye == PitchingCourse.Center || ballData.PitchingCourseByBattingEye == PitchingCourse.Sweet) && !ballData.IsFastBall) { // ど真ん中か甘いコースで変化球のみスイング swingData.IsSwing = true; swingData.TargetBollSwingLevel = 2; } else { if (gameData.StrikeCount < 2) { // 条件に合わなければスイングしない swingData.IsSwing = false; } else { // 追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } break; #endregion #region クサイ所はカット case BattingMissionKind.CutScantBall: // クサイ所はカット if (gameData.StrikeCount == 2 && (ballData.PitchingCourse == PitchingCourse.Severe || ballData.PitchingCourse == PitchingCourse.Corner) && ballData.PitchingCourseByBattingEye == PitchingCourse.ScantBall) { // 2ストライクで「厳しいボール」を誤判断で「わずかにボール」と判定した場合に // 一定確率でカットする(智力依存) GameMemberAbility memberAbility = gameData.CurrentBatterAbirity; double percent = GameMemberAbility.GetHigherValueOverBaseline(memberAbility.Wisdom, Constants.MaxCutScantBollPercent); if (RandomCreater.GetPercentValue() < percent) { swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } break; #endregion #region 送りバント case BattingMissionKind.Bunt: // 送りバント if (gameData.UnableBunt) { break; } // 二塁→三塁へのバントは一死では効果が低いため実施しない // (一死二塁と一死一二塁はバントしない) if (gameData.OutCount == 1 && gameData.SecondRunnerMember != null) { break; } // 智力が打力以上であり // 次の打者の打者能力が現在の打者より著しく劣っていない if (gameData.CurrentBatter.Wisdom >= gameData.CurrentBatter.MeetAndPower && gameData.NextBatter.BatterAbility > gameData.CurrentBatter.BatterAbility - Constants.BatterAbilityDeltaForBunt) { // 試合出場中メンバのうち、打者能力上位3名はバントしない var goodBatters = gameData.CurrentAttackTeam.CurrentPlayingMembers.OrderByDescending(m => m.BatterAbility).Take(3); if (goodBatters.SingleOrDefault(m => m == gameData.CurrentBatter) == null) { swingData.BattingSwingKind = BattingSwingKind.Bunt; if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { swingData.IsSwing = true; } // ストライクと判断しない場合にスイングをやめる処理は行わない // クサイ球をカットするためにスイングする状態になっているのをそのまま活用してストライクを見逃さない } } break; #endregion #region 出塁狙い case BattingMissionKind.TargetFourBall: // 四球狙い // 智力が打力より圧倒的に高い場合に適用する if (gameData.CurrentBatter.Wisdom - gameData.CurrentBatter.MeetAndPower >= Constants.TargetFourBollMeetAndPowerDelta) { if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { if (gameData.StrikeCount < 2) { // 2ストライクまではスイングしない swingData.IsSwing = false; } else { // 追い込まれていればファウル狙い swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Cut; } } } break; case BattingMissionKind.SafetyBunt: // セーフティバント if (gameData.UnableSafetyBunt || gameData.CurrentBatter.SafetyBuntAbility <= gameData.CurrentBatter.MeetAndPower || (gameData.AllRunnerMembers.Count > 0 && gameData.AllRunnerMembers.Min(r => r.RunnerAbility) < Constants.RunAbilityForBuntRunner)) { // 以下の場合は実行しない // ・セーフティバント実施すべきでない状況(走力足りない、2ストライク、バントシフト) // ・「セーフティバント能力」が「ミート+パワー」以下 // ・ランナーがいる場合に走塁能力が一定以上ないランナーがいる // (足が遅すぎるとランナーがアウトになるため) break; } // セーフティバント能力が、三塁手の守備力を大幅に超えている場合に実行 // (前進守備しているかどうかで必要な差分は異なる) { double delta = (gameData.CurrentBatter.SafetyBuntAbility) - (gameData.GetDefenseMember(DefensePosition.Third).Defense); if ((gameData.InFielderDrawIn == false && delta >= Constants.DeltaForSafetyBunt) || (gameData.InFielderDrawIn == true && delta >= Constants.DeltaForBuntShift)) { swingData.BattingSwingKind = BattingSwingKind.SafetyBunt; if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { swingData.IsSwing = true; } } } break; #endregion #region 盗塁・スクイズ case BattingMissionKind.Steal: // 盗塁 if (RunnerTactics.TrySteal(gameData)) { swingData.IsSteal = true; if (gameData.StrikeCount < 2) { // 追い込まれていない場合 // (見逃す場合でもアニメーションで使用するため、スイングの種類はバントにする) swingData.IsSwing = false; swingData.BattingSwingKind = BattingSwingKind.Bunt; } else { // 追い込まれている場合 // スイング有無とスイング種別は変更しない // (カット狙いや長打狙いをやめて転がせにするとデメリットがあるため) } } break; case BattingMissionKind.Squeeze: // スクイズ if (gameData.UnableSqueeze) { break; } // 打者の智力がミート・パワーの平均より低い場合は実施しない(打った方が期待できるため) if (gameData.CurrentBatter.Wisdom < gameData.CurrentBatter.MeetAndPower) { break; } // 試合出場中メンバのうち、打者能力上位2名はスクイズしない var highBatters = gameData.CurrentAttackTeam.CurrentPlayingMembers.OrderByDescending(m => m.BatterAbility).Take(2); if (highBatters.Any(m => m == gameData.CurrentBatter)) { break; } int squeezeValue = 0; if (gameData.StrikeCount + gameData.BallCount == 0) { // 初球 squeezeValue = 10; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 0) { // 2球目(ストライク先行) squeezeValue = 10; } else if (gameData.StrikeCount == 0 && gameData.BallCount == 1) { // 2球目(ボール先行) squeezeValue = 20; } else if (gameData.StrikeCount == 1 && gameData.BallCount == 1) { // 3球目の並行カウント squeezeValue = 20; } else if (gameData.StrikeCount == 2) { // 追い込まれるとスクイズなし squeezeValue = 0; } else if (gameData.StrikeCount == 0 && gameData.BallCount >= 2) { // ストライク一球もなければ逆に敬遠の可能性があるため控える squeezeValue = 10; } else if (gameData.StrikeCount == 1 && gameData.BallCount >= 2) { // ストライク一球あってボール先行であれば敬遠のリスクも低くスクイズのチャンス squeezeValue = 20; } // 指定した確率でスクイズを実行するか判定 if (RandomCreater.GetPercentValue() < squeezeValue) { swingData.AllRunnerStart = true; swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Squeeze; } break; #endregion #region ユーザ操作による最優先作戦 // スクイズ作戦を自動で実行している可能性があるため、全ランナースタートフラグをリセットする // 盗塁も自動で実行している可能性があるが、それはそれで効果的なのでフラグリセットしない case BattingMissionKind.SafetyBuntByUser: // セーフティバント(ユーザ操作) // (見逃す場合でもアニメーションで使用するため、スイングの種類はバントにする) swingData.AllRunnerStart = false; swingData.BattingSwingKind = BattingSwingKind.SafetyBunt; if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { swingData.IsSwing = true; } // ストライクと判断しない場合にスイングをやめる処理は行わない // クサイ球をカットするためにスイングする状態になっているのをそのまま活用してストライクを見逃さない break; case BattingMissionKind.BuntByUser: // 送りバント(ユーザ操作) // (見逃す場合でもアニメーションで使用するため、スイングの種類はバントにする) swingData.AllRunnerStart = false; swingData.BattingSwingKind = BattingSwingKind.Bunt; if (PitchingCourseHelper.IsStrike(ballData.PitchingCourseByBattingEye)) { swingData.IsSwing = true; } // ストライクと判断しない場合にスイングをやめる処理は行わない // クサイ球をカットするためにスイングする状態になっているのをそのまま活用してストライクを見逃さない break; case BattingMissionKind.SqueezeByUser: // スクイズ(ユーザ操作) { swingData.AllRunnerStart = true; swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.Squeeze; } break; case BattingMissionKind.StealByUser: // 盗塁(ユーザ操作) // (見逃す場合でもアニメーションで使用するため、スイングの種類はバントにする) swingData.AllRunnerStart = false; swingData.IsSwing = false; swingData.BattingSwingKind = BattingSwingKind.Bunt; swingData.IsSteal = true; break; case BattingMissionKind.EndRunByUser: // エンドラン(ユーザ操作) swingData.AllRunnerStart = true; swingData.IsSwing = true; swingData.BattingSwingKind = BattingSwingKind.EndRun; break; case BattingMissionKind.WaitByUser: // 待て(ユーザ操作) swingData.AllRunnerStart = false; swingData.IsSwing = false; break; #endregion default: throw new Exception("Invalid BattingMissinKind"); } return swingData; }
/// <summary> /// 消滅 /// </summary> public void Dispose() { GameData = null; }