コード例 #1
0
        /// <summary>
        /// ランナーの進塁/帰塁/停止を設定する(進塁停止していたランナーは残り到達時間が0のため、こちらを用いる)
        /// </summary>
        /// <param name="runnerStatus">更新するランナー</param>
        private void UpdateRunnerStatusForForwardOrBack(RunnerStatus runnerStatus)
        {
            int remainingTimeToNextBase;

            if (runnerStatus.IsStop || runnerStatus.RemainingTimeToNextBase == 0)
            {
                // 残り到達時間が0であれば、塁間距離から次の塁までの走塁にかかる時間を取得して判定
                remainingTimeToNextBase = GetRemainingTimeToNextBase(runnerStatus.Run, Constants.BaseDistance);
            }
            else
            {
                // 進塁中であれば残り到達時間をそのまま用いる
                remainingTimeToNextBase = runnerStatus.RemainingTimeToNextBase;
            }
            UpdateRunnerStatusForForwardOrBack(runnerStatus, remainingTimeToNextBase);
        }
コード例 #2
0
        /// <summary>
        /// ランナーの進塁/帰塁/停止を設定する
        /// </summary>
        /// <param name="runnerStatus">更新するランナー</param>
        /// <param name="remainingTimeToNextBase">次の塁への残り到達時間</param>
        private void UpdateRunnerStatusForForwardOrBack(RunnerStatus runnerStatus, int remainingTimeToNextBase)
        {
            // 帰塁中は何も更新しない
            if (runnerStatus.BackRun)
            {
                return;
            }

            // 次の塁の取得
            int nextBase = runnerStatus.OverBaseCount + 1;

            // 前のランナーが次の塁にとどまるならば進塁しない(ホームは重複してもよい)
            if (GameData.AllRunnerStatus.Where(r => r.RunnerNumber > runnerStatus.RunnerNumber).Any(
                preRunner => preRunner.FinalTargetBase < (int)BaseKind.HomeBase && preRunner.FinalTargetBase <= nextBase))
            {
                SetRunnerStatusForStopOrBack(runnerStatus);
                return;
            }

            // 盗塁・エンドランのランナーは、初回の判定時、次の塁までは必ず進塁する
            bool forwardRun = GameData.AllDefensePassedSecond == 0 && runnerStatus.IsSteal && nextBase == runnerStatus.RunnerNumber + 1;

            // 送球完了までの時間を取得
            int throwFinishTime = GetThrowFinishTime(nextBase);

            // 余裕時間の取得(0より大きければ進塁可能、0以下なら進塁不可)
            int marginTime = throwFinishTime - remainingTimeToNextBase;

            // デバッグ用文字列の設定
            runnerStatus.DebugInfo = string.Format("throwFinishTime={0}, remainingTimeToNextBase={1}", throwFinishTime, remainingTimeToNextBase);

            // 進塁するか智力で判定
            // (盗塁・エンドランのランナーは、次の塁までは必ず進塁すると判定する)
            if (JudgeForwardRun(runnerStatus, runnerStatus.OverBaseCount + 1, marginTime) || forwardRun)
            {
                runnerStatus.RemainingTimeToNextBase = remainingTimeToNextBase;
                runnerStatus.IsStop = false;
                runnerStatus.BackRun = false;

                // 進塁する場合、どこまで進塁するか設定する
                runnerStatus.FinalTargetBase = GetFinalTargetBase(runnerStatus, marginTime);
            }
            else
            {
                // 進塁しない
                SetRunnerStatusForStopOrBack(runnerStatus);
            }
        }
コード例 #3
0
        /// <summary>
        /// ランナーを進塁しないように設定する(停止するか帰塁する)
        /// </summary>
        /// <param name="runnerStatus"></param>
        private void SetRunnerStatusForStopOrBack(RunnerStatus runnerStatus)
        {
            if (runnerStatus.RemainingTimeToNextBase <= 0 && !runnerStatus.NeedBackRun)
            {
                // 塁にとどまっているなら停止する
                runnerStatus.BackRun = false;
                runnerStatus.IsStop = true;
                LastRunnerStopTime = GameData.AllDefensePassedSecond;
            }
            else
            {
                // 塁間にいる場合は帰塁する(ただし一塁より前には帰塁できない)
                if (runnerStatus.OverBaseCount >= 1)
                {
                    runnerStatus.IsStop = false;
                    if (!runnerStatus.BackRun)
                    {
                        // もともと帰塁中でなければ残り到達時間を更新する
                        runnerStatus.BackRun = true;
                        int needTimeToNextBase = GetRemainingTimeToNextBase(runnerStatus.Run, Constants.BaseDistance);
                        runnerStatus.RemainingTimeToNextBase = needTimeToNextBase - runnerStatus.RemainingTimeToNextBase;
                    }
                }
            }

            // 先行するランナーに追いつこうとしている場合は帰塁させる
            foreach (RunnerStatus followRunner
                in GameData.AllRunnerStatus.Where(r => r.RunnerNumber < runnerStatus.RunnerNumber &&
                    r.TargetBase >= runnerStatus.TargetBase && !r.BackRun))
            {
                SetRunnerStatusForStopOrBack(followRunner);
            }
        }
コード例 #4
0
        /// <summary>
        /// ランナーの更新(単位時間分移動させる)
        /// </summary>
        /// <param name="runnerStatus"></param>
        private void UpdateRunnerStatus(RunnerStatus runnerStatus)
        {
            // ランナーが存在しないか進塁ストップの場合は何もしない
            if (runnerStatus == null || runnerStatus.IsStop)
            {
                return;
            }

            // ランナーの移動(残り時間を減算)
            runnerStatus.RemainingTimeToNextBase -= Constants.PassSecondByTurn;

            // ランナーの現在位置の更新
            MPoint targetPoint = GameData.GetBasePoint(runnerStatus.TargetBase);
            MPoint startPoint = GameData.GetBasePoint(runnerStatus.FromBase);
            Vector moveVoctor = targetPoint - startPoint;
            double progress = (double)(runnerStatus.AllTimeForBaseDistance - runnerStatus.RemainingTimeToNextBase) / runnerStatus.AllTimeForBaseDistance;
            runnerStatus.Point = startPoint + moveVoctor * progress;

            // 次の塁に到達したか
            if (runnerStatus.RemainingTimeToNextBase <= 0)
            {
                // 位置の更新(速度だけでは微妙にずれるので到達したときに補正)
                switch (runnerStatus.TargetBase)
                {
                    case 1:
                        runnerStatus.Point = Constants.PointFirstBase;
                        break;
                    case 2:
                        runnerStatus.Point = Constants.PointSecondBase;
                        break;
                    case 3:
                        runnerStatus.Point = Constants.PointThirdBase;
                        break;
                    case 4:
                        runnerStatus.Point = Constants.PointHomeBase;
                        break;
                    default:
                        throw new Exception("Invalid TargetBase next");
                }

                // ファウル時、フライの落下前、フォースアウトで3アウトになりうる場合は本塁に到達したことにならない
                // (フライとして捕球されるか、チェンジになる可能性があるため)
                if (runnerStatus.TargetBase == 4)
                {
                    // ファウルの場合は本塁到達不可
                    if (IsFoul)
                    {
                        return;
                    }

                    // フライの落下前は本塁到達不可
                    if (GameData.IsBattedBollFlying)
                    {
                        return;
                    }

                    // フォースアウトで3アウトになりうる場合は本塁に到達したことならない
                    int forceOutCount = 0;
                    if (IsForceOut(1)) forceOutCount++;
                    if (IsForceOut(2)) forceOutCount++;
                    if (IsForceOut(3)) forceOutCount++;
                    if (forceOutCount + GameData.OutCount >= 3)
                    {
                        return;
                    }
                }

                // タッチアウト待ちか
                if (GameData.DefenseTermKind == DefenseTermKind.WaitingRunner)
                {
                    // 到達した塁がタッチアウト待ちの塁か
                    if (runnerStatus.TargetBase == ThrowTargetBase)
                    {
                        // タッチアウトになる
                        SetOutRunner(runnerStatus, ThrowPosition);

                        // 守備側が他の塁へ送球するか判定
                        JudgeAnotherThrowTaget();

                        return;
                    }
                }

                // ここまで来たら次の塁に到達完了

                if (!runnerStatus.BackRun)
                {
                    // 進塁の場合は通過したベース数を加算
                    runnerStatus.OverBaseCount++;

                    if (runnerStatus.OverBaseCount >= 4)
                    {
                        // ホームに到達した場合は得点
                        AddScore(runnerStatus.RunnerNumber);
                    }
                    else
                    {
                        // ホーム以外に進塁した場合は、次の塁に進むか判定
                        UpdateRunnerStatusForForwardOrBack(runnerStatus);
                    }
                }
                else
                {
                    // 帰塁中の場合

                    // さらに帰塁する必要があるか判定
                    if (runnerStatus.NeedBackRun && runnerStatus.TargetBase != runnerStatus.RunnerNumber)
                    {
                        // さらに帰塁する必要があれば、かかる時間を設定
                        runnerStatus.OverBaseCount--;
                        runnerStatus.RemainingTimeToNextBase = GetRemainingTimeToNextBase(runnerStatus.Run, Constants.BaseDistance);
                    }
                    else
                    {
                        // 元の塁まで戻ってきたら停止
                        runnerStatus.NeedBackRun = false;
                        runnerStatus.BackRun = false;
                        runnerStatus.IsStop = true;
                        LastRunnerStopTime = GameData.AllDefensePassedSecond;

                        // 帰塁完了した時点ですでにフライが落下後であれば進塁の最判断
                        if (!GameData.IsBattedBollFlying)
                        {
                            UpdateRunnerStatusForForwardOrBack(runnerStatus);
                        }
                    }
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// 指定したランナーをアウトにする
        /// </summary>
        /// <param name="runnerStatus">アウトにするランナー</param>
        /// <param name="defensePosition">アウトにする守備位置</param>
        /// <param name="isAssistOut">捕殺か(捕殺ならtrue、刺殺ならfalse)</param>
        private void SetOutRunner(RunnerStatus runnerStatus, DefensePosition defensePosition, bool isAssistOut = true)
        {
            // アウトカウントの加算
            CurrentBatterOutCount++;

            // 併殺のためのアウトカウント加算
            // ゴロであり、元の塁か次の塁でアウトになった場合のみカウント
            // (ゴロで元の塁でアウトになるのはレアケースだが一応考慮しておく)
            // (フライアウト、帰塁できないアウト、オーバーランはカウントしない)
            if (!CurrentFlyOut &&
                (runnerStatus.TargetBase == runnerStatus.RunnerNumber ||
                 runnerStatus.TargetBase == runnerStatus.RunnerNumber + 1))
            {
                CurrentBatterForceOutCount++;
            }

            // 打撃結果の設定
            SetBattingResultByOut(defensePosition);

            // 指定したランナーをアウトにする
            GameData.SetOutRunner(runnerStatus.RunnerNumber);

            // 捕殺・刺殺の加算
            GameData.GetDefenseMember(defensePosition).AddOutCount(isAssistOut);

            // アウトのイベント発行
            if (JudgedSafeOrOut != null)
            {
                JudgedSafeOrOut(false);
            }
        }
コード例 #6
0
        /// <summary>
        /// ランナーが進塁するかしないか判定する
        /// </summary>
        /// <param name="runnerStatus">対象ランナー</param>
        /// <param name="targetBase">次の塁</param>
        /// <param name="marginTime">誤判断せず正しく判断できる時間</param>
        /// <returns>進塁するか</returns>
        private bool JudgeForwardRun(RunnerStatus runnerStatus, int targetBase, int marginTime)
        {
            // ランナー初期化の時点で、パスボールでなく2アウトであれば、元の塁から次の塁までは必ず進塁する
            if (GameData.AllDefensePassedSecond == 0 && IsBattedBollMode &&
                GameData.OutCount == 2 && targetBase == runnerStatus.RunnerNumber + 1)
            {
                return true;
            }

            // フォースアウト対象であれば、無条件で進塁する
            // (FinalTargetBaseの判定も行うため、ランナーの元の塁も判定に含める)
            if (IsForceOut(targetBase) && targetBase == runnerStatus.RunnerNumber + 1)
            {
                return true;
            }

            // 実際に進塁可能かどうかを元に判定を分岐
            GameMemberAbility memberAbility = runnerStatus.MemberAbility;
            if (marginTime <= 0)
            {
                // 進塁できない場合

                // アホでも、試合バランスを維持するために無謀な進塁はしない
                // ただし、二死で捕逸以外でのホームへの進塁のみ無謀に暴走する(プロ野球でもよくある)
                // (捕逸でホームで刺されることがよくあるため、捕逸は暴走しないようにしている)
                if (GameData.OutCount == 2 && targetBase == 4 && !GameData.LatestPitchingBollResult.BattedBoll.IsPassBoll &&
                    !JudgeCorrectRun(memberAbility, marginTime))
                {
                    // 無謀に進塁
                    return true;
                }
                else
                {
                    // 正しく停止
                    return false;
                }
            }
            else
            {
                // 進塁できる場合

                // 賢いほど、ぎりぎり間にあう状態で積極的に進塁する
                // (アホだと、せっかくのチャンスに進塁しない)
                // ただし、二死でホームへの進塁時は進塁する
                if (JudgeCorrectRun(memberAbility, marginTime) ||
                    (GameData.OutCount == 2 && targetBase == 4))
                {
                    // 正しく進塁
                    return true;
                }
                else
                {
                    // 進塁できるのに停止
                    return false;
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// 打球を元に、ランナーの進塁/帰塁を設定する
        /// (進塁の場合は最終的に到達予定の塁も設定する)
        /// </summary>
        /// <param name="runnerStatus">ランナー状態</param>
        private void InitializeRunnerStatus(RunnerStatus runnerStatus)
        {
            // ファウル方向へのフライの場合は進塁しない
            if (GameData.LatestPitchingBollResult.BattedBoll.IsFoulDirection &&
                GameData.LatestPitchingBollResult.BattedBoll.DropTime > 0)
            {
                SetRunnerStatusForStopOrBack(runnerStatus);
                return;
            }

            // 正しく判断可能な余裕時間を算出する
            // (この値より大きい余裕時間であれば、正しくフライがキャッチされることを判断できる)
            int correctJudgeTime = (int)GameMemberAbility.GetLowerValue(runnerStatus.Wisdom, Constants.MaxWrongJudgeTimeForFlyCatch);

            // フライキャッチされるかで分岐
            if (CanCatchFly && MoveDropPointDeltaTime >= correctJudgeTime && GameData.OutCount < 2)
            {
                // フライキャッチされる(と判断した)場合
                // 賢いほど、ぎりぎりでフライを捕球した場合でも前の塁に戻る
                // 2アウトならばフライでも帰塁しない
                if (runnerStatus.RunnerNumber != 0)
                {
                    // 打者ランナーはフライで取られる場合もとりあえず一塁に進むため、何もしない
                    SetRunnerStatusForStopOrBack(runnerStatus);
                }
            }
            else
            {
                // フライキャッチされない(と判断した)場合

                // 次の塁までかかる残り時間を元に、進塁/帰塁と最終到達予定塁を設定する
                UpdateRunnerStatusForForwardOrBack(runnerStatus);
            }
        }
コード例 #8
0
        /// <summary>
        /// 最終到達予定の塁を取得する
        /// </summary>
        /// <param name="runnerStatus"></param>
        /// <param name="marginTime"></param>
        /// <returns></returns>
        private int GetFinalTargetBase(RunnerStatus runnerStatus, int marginTime)
        {
            Assertion.Assert(!runnerStatus.IsStop && !runnerStatus.BackRun, "!runnerStatus.IsStop && !runnerStatus.BackRun");

            // 現在の塁からどこまで進塁可能か判断する
            int nextBase = runnerStatus.TargetBase;
            int finalTargetBase = nextBase;
            for (int i = nextBase + 1; i <= 4; i++)
            {
                // 次の次の塁まで到達するのにかかる時間を余裕時間から減算する
                marginTime -= GetRemainingTimeToNextBase(runnerStatus.Run, Constants.BaseDistance);

                // 進塁可能か判定する
                if (JudgeForwardRun(runnerStatus, i, marginTime))
                {
                    finalTargetBase = i;
                }
                else
                {
                    break;
                }
            }

            return finalTargetBase;
        }
コード例 #9
0
ファイル: GameData.cs プロジェクト: koji716jp/eikannyain
 /// <summary>
 /// 指定したランナー情報の設定
 /// (この時点ではランナーメンバは更新せず打席終了時に更新する)
 /// </summary>
 /// <param name="runnerNumber"></param>
 /// <param name="runnerStatus"></param>
 public void SetRunnerStatus(int runnerNumber, RunnerStatus runnerStatus)
 {
     switch (runnerNumber)
     {
         case 0:
             BatterRunnerStatus = runnerStatus;
             break;
         case 1:
             FirstRunnerStatus = runnerStatus;
             break;
         case 2:
             SecondRunnerStatus = runnerStatus;
             break;
         case 3:
             ThirdRunnerStatus = runnerStatus;
             break;
         default:
             throw new Exception("Invalid RunnerNumber");
     }
 }