From fd159ac58248b3a5ef63ddb8a1c35ab492ddc716 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Sun, 10 Apr 2022 16:09:49 +1000 Subject: [PATCH] Some cleanup --- 07_Basketball/csharp/Plays/HomeTeamPlay.cs | 19 ++++++++----------- .../csharp/Plays/VisitingTeamPlay.cs | 8 +++++--- 07_Basketball/csharp/Probably.cs | 6 ++++++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/07_Basketball/csharp/Plays/HomeTeamPlay.cs b/07_Basketball/csharp/Plays/HomeTeamPlay.cs index 999a6551..cb614af2 100644 --- a/07_Basketball/csharp/Plays/HomeTeamPlay.cs +++ b/07_Basketball/csharp/Plays/HomeTeamPlay.cs @@ -9,6 +9,7 @@ internal class HomeTeamPlay : Play private readonly IRandom _random; private readonly Clock _clock; private readonly Defense _defense; + private readonly BallContest _ballContest; private bool _playContinues; public HomeTeamPlay(TextIO io, IRandom random, Clock clock, Defense defense) @@ -18,6 +19,7 @@ internal class HomeTeamPlay : Play _random = random; _clock = clock; _defense = defense; + _ballContest = new BallContest(0.5f, "Shot is blocked. Ball controlled by {0}.", _io, _random); } internal override bool Resolve(Scoreboard scoreboard) @@ -39,10 +41,13 @@ internal class HomeTeamPlay : Play Resolve(jumpShot, scoreboard); } + // Either the above resolution has transition to a lay-up + // or the chosen shot is not a jump shot and has not been resolved yet. _playContinues |= shot is not JumpShot; while (_playContinues) { + _playContinues = false; if (ClockIncrementsToHalfTime(scoreboard)) { return false; } Resolve(shot, scoreboard); } @@ -50,29 +55,21 @@ internal class HomeTeamPlay : Play return false; } - private void Resolve(JumpShot shot, Scoreboard scoreboard) - { - var ballContest = new BallContest(0.5f, "Shot is blocked. Ball controlled by {0}.", _io, _random); - + private void Resolve(JumpShot shot, Scoreboard scoreboard) => Resolve(shot.ToString(), _defense / 8) .Do(0.341f, () => scoreboard.AddBasket("Shot is good")) .Or(0.682f, () => ResolveShotOffTarget(scoreboard)) - .Or(0.782f, () => ballContest.Resolve(scoreboard)) + .Or(0.782f, () => _ballContest.Resolve(scoreboard)) .Or(0.843f, () => ResolveFreeThrows(scoreboard, "Shooter is fouled. Two shots.")) .Or(() => scoreboard.Turnover($"Charging foul. {scoreboard.Home} loses ball.")); - } - - private void Resolve(Shot shot, Scoreboard scoreboard) - { - _playContinues = false; + private void Resolve(Shot shot, Scoreboard scoreboard) => Resolve(shot.ToString(), _defense / 7) .Do(0.4f, () => scoreboard.AddBasket("Shot is good. Two points.")) .Or(0.7f, () => ResolveShotOffTheRim(scoreboard)) .Or(0.875f, () => ResolveFreeThrows(scoreboard, "Shooter fouled. Two shots.")) .Or(0.925f, () => scoreboard.Turnover($"Shot blocked. {scoreboard.Visitors}'s ball.")) .Or(() => scoreboard.Turnover($"Charging foul. {scoreboard.Home} loses ball.")); - } private void ResolveShotOffTarget(Scoreboard scoreboard) => Resolve("Shot is off target", 6 / _defense) diff --git a/07_Basketball/csharp/Plays/VisitingTeamPlay.cs b/07_Basketball/csharp/Plays/VisitingTeamPlay.cs index 1722be02..f7ac45a0 100644 --- a/07_Basketball/csharp/Plays/VisitingTeamPlay.cs +++ b/07_Basketball/csharp/Plays/VisitingTeamPlay.cs @@ -31,6 +31,8 @@ internal class VisitingTeamPlay : Play _io.WriteLine(); } + // Either the above resolution has transition to a lay-up + // or the chosen shot is not a jump shot and has not been resolved yet. _playContinues |= shot is not JumpShot; while (_playContinues) @@ -48,7 +50,7 @@ internal class VisitingTeamPlay : Play .Do(0.35f, () => scoreboard.AddBasket("Shot is good.")) .Or(0.75f, () => ResolveBadShot(scoreboard, "Shot is off the rim.", _defense * 6)) .Or(0.9f, () => ResolveFreeThrows(scoreboard, "Player fouled. Two shots.")) - .Or(() => _io.WriteLine("Offensive foul. Dartmouth's ball.")); + .Or(() => _io.WriteLine($"Offensive foul. {scoreboard.Home}'s ball.")); private void Resolve(Shot shot, Scoreboard scoreboard) => Resolve(shot.ToString(), _defense / 7) @@ -57,7 +59,7 @@ internal class VisitingTeamPlay : Play void ResolveBadShot(Scoreboard scoreboard, string message, float defenseFactor) => Resolve(message, defenseFactor) - .Do(0.5f, () => scoreboard.Turnover("Dartmouth controls the rebound.")) + .Do(0.5f, () => scoreboard.Turnover($"{scoreboard.Home} controls the rebound.")) .Or(() => ResolveVisitorsRebound(scoreboard)); void ResolveVisitorsRebound(Scoreboard scoreboard) @@ -67,7 +69,7 @@ internal class VisitingTeamPlay : Play { _io.WriteLine(); scoreboard.Turnover(); - scoreboard.AddBasket("Ball stolen. Easy lay up for Dartmouth."); + scoreboard.AddBasket($"Ball stolen. Easy lay up for {scoreboard.Home}."); return; } diff --git a/07_Basketball/csharp/Probably.cs b/07_Basketball/csharp/Probably.cs index a7ca403c..1a32674e 100644 --- a/07_Basketball/csharp/Probably.cs +++ b/07_Basketball/csharp/Probably.cs @@ -2,6 +2,12 @@ using Games.Common.Randomness; namespace Basketball; +/// +/// Supports a chain of actions to be performed based on various probabilities. The original game code gets a new +/// random number for each probability check. Evaluating a set of probabilities against a single random number is +/// much simpler, but yield a very different outcome distribution. The purpose of this class is to simplify the code +/// to for the original probabilistic branch decisions. +/// internal struct Probably { private readonly float _defenseFactor;