mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-01-03 00:30:36 -08:00
Resolve play resolution helper methods
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
using Basketball.Resources;
|
||||
using Games.Common.IO;
|
||||
using Games.Common.Randomness;
|
||||
|
||||
@@ -10,9 +9,10 @@ internal class HomeTeamPlay : Play
|
||||
private readonly IRandom _random;
|
||||
private readonly Clock _clock;
|
||||
private readonly Defense _defense;
|
||||
private bool _playContinues;
|
||||
|
||||
public HomeTeamPlay(TextIO io, IRandom random, Clock clock, Defense defense)
|
||||
: base(io, random)
|
||||
: base(io, random, clock)
|
||||
{
|
||||
_io = io;
|
||||
_random = random;
|
||||
@@ -33,61 +33,69 @@ internal class HomeTeamPlay : Play
|
||||
return false;
|
||||
}
|
||||
|
||||
var playContinues = shot >= 3;
|
||||
|
||||
if (shot == 1 || shot == 2)
|
||||
{
|
||||
_clock.Increment(scoreboard);
|
||||
if (_clock.IsHalfTime) { return false; }
|
||||
|
||||
var ballContest = new BallContest(0.5f, "Shot is blocked. Ball controlled by {0}.", _io, _random);
|
||||
|
||||
Resolve("Jump shot", _defense / 8)
|
||||
.Do(0.341f, () => scoreboard.AddBasket("Shot is good"))
|
||||
.Or(0.682f, () => ResolveShotOffTarget())
|
||||
.Or(0.782f, () => ballContest.Resolve(scoreboard))
|
||||
.Or(0.843f, () => ResolveFreeThrows(scoreboard, "Shooter is fouled. Two shots."))
|
||||
.Or(() => scoreboard.Turnover("Charging foul. Dartmouth loses ball."));
|
||||
if (ClockIncrementsToHalfTime(scoreboard)) { return false; }
|
||||
ResolveJumpShot(scoreboard);
|
||||
}
|
||||
|
||||
while (playContinues)
|
||||
_playContinues |= shot >= 3;
|
||||
|
||||
while (_playContinues)
|
||||
{
|
||||
_clock.Increment(scoreboard);
|
||||
if (_clock.IsHalfTime) { return false; }
|
||||
|
||||
playContinues = false;
|
||||
|
||||
Resolve(shot == 3 ? "Lay up." : "Set shot.", _defense / 7)
|
||||
.Do(0.4f, () => scoreboard.AddBasket("Shot is good. Two points."))
|
||||
.Or(0.7f, () => ResolveShotOffTheRim())
|
||||
.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. Dartmouth loses ball."));
|
||||
if (ClockIncrementsToHalfTime(scoreboard)) { return false; }
|
||||
ResolveLayupOrSetShot(scoreboard, shot);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
void ResolveShotOffTarget() =>
|
||||
Resolve("Shot is off target", 6 / _defense)
|
||||
.Do(0.45f, () => Resolve("Dartmouth controls the rebound.")
|
||||
.Do(0.4f, () => playContinues = true)
|
||||
.Or(() =>
|
||||
{
|
||||
if (_defense == 6 && _random.NextFloat() > 0.6f)
|
||||
{
|
||||
scoreboard.Turnover();
|
||||
scoreboard.AddBasket($"Pass stolen by {scoreboard.Visitors} easy layup.");
|
||||
_io.WriteLine();
|
||||
}
|
||||
_io.Write("Ball passed back to you. ");
|
||||
}))
|
||||
.Or(() => scoreboard.Turnover($"Rebound to {scoreboard.Visitors}"));
|
||||
|
||||
void ResolveShotOffTheRim() =>
|
||||
Resolve("Shot is off the rim.")
|
||||
.Do(2 / 3f, () => scoreboard.Turnover($"{scoreboard.Visitors} controls the rebound."))
|
||||
.Or(() => Resolve("Dartmouth controls the rebound")
|
||||
.Do(0.4f, () => playContinues = true)
|
||||
.Or(() => _io.WriteLine("Ball passed back to you.")));
|
||||
}
|
||||
|
||||
private void ResolveJumpShot(Scoreboard scoreboard)
|
||||
{
|
||||
var ballContest = new BallContest(0.5f, "Shot is blocked. Ball controlled by {0}.", _io, _random);
|
||||
|
||||
Resolve("Jump shot", _defense / 8)
|
||||
.Do(0.341f, () => scoreboard.AddBasket("Shot is good"))
|
||||
.Or(0.682f, () => ResolveShotOffTarget(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 ResolveLayupOrSetShot(Scoreboard scoreboard, int shot)
|
||||
{
|
||||
_playContinues = false;
|
||||
|
||||
Resolve(shot == 3 ? "Lay up." : "Set shot.", _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)
|
||||
.Do(0.45f, () => ResolveHomeRebound(scoreboard, ResolvePossibleSteal))
|
||||
.Or(() => scoreboard.Turnover($"Rebound to {scoreboard.Visitors}"));
|
||||
|
||||
private void ResolveHomeRebound(Scoreboard scoreboard, Action<Scoreboard> endOfPlayAction) =>
|
||||
Resolve($"{scoreboard.Home} controls the rebound.")
|
||||
.Do(0.4f, () => _playContinues = true)
|
||||
.Or(() => endOfPlayAction.Invoke(scoreboard));
|
||||
private void ResolvePossibleSteal(Scoreboard scoreboard)
|
||||
{
|
||||
if (_defense == 6 && _random.NextFloat() > 0.6f)
|
||||
{
|
||||
scoreboard.Turnover();
|
||||
scoreboard.AddBasket($"Pass stolen by {scoreboard.Visitors} easy layup.");
|
||||
_io.WriteLine();
|
||||
}
|
||||
_io.Write("Ball passed back to you. ");
|
||||
}
|
||||
|
||||
private void ResolveShotOffTheRim(Scoreboard scoreboard) =>
|
||||
Resolve("Shot is off the rim.")
|
||||
.Do(2 / 3f, () => scoreboard.Turnover($"{scoreboard.Visitors} controls the rebound."))
|
||||
.Or(() => ResolveHomeRebound(scoreboard, _ => _io.WriteLine("Ball passed back to you.")));
|
||||
}
|
||||
|
||||
@@ -7,11 +7,19 @@ internal abstract class Play
|
||||
{
|
||||
private readonly IReadWrite _io;
|
||||
private readonly IRandom _random;
|
||||
private readonly Clock _clock;
|
||||
|
||||
public Play(IReadWrite io, IRandom random)
|
||||
public Play(IReadWrite io, IRandom random, Clock clock)
|
||||
{
|
||||
_io = io;
|
||||
_random = random;
|
||||
_clock = clock;
|
||||
}
|
||||
|
||||
protected bool ClockIncrementsToHalfTime(Scoreboard scoreboard)
|
||||
{
|
||||
_clock.Increment(scoreboard);
|
||||
return _clock.IsHalfTime;
|
||||
}
|
||||
|
||||
internal abstract bool Resolve(Scoreboard scoreboard);
|
||||
|
||||
@@ -7,52 +7,59 @@ internal class VisitingTeamPlay : Play
|
||||
{
|
||||
private readonly TextIO _io;
|
||||
private readonly IRandom _random;
|
||||
private readonly Clock _clock;
|
||||
private readonly Defense _defense;
|
||||
private bool _playContinues;
|
||||
|
||||
public VisitingTeamPlay(TextIO io, IRandom random, Clock clock, Defense defense)
|
||||
: base(io, random)
|
||||
: base(io, random, clock)
|
||||
{
|
||||
_io = io;
|
||||
_random = random;
|
||||
_clock = clock;
|
||||
_defense = defense;
|
||||
}
|
||||
|
||||
internal override bool Resolve(Scoreboard scoreboard)
|
||||
{
|
||||
_clock.Increment(scoreboard);
|
||||
if (_clock.IsHalfTime) { return false; }
|
||||
if (ClockIncrementsToHalfTime(scoreboard)) { return false; }
|
||||
|
||||
_io.WriteLine();
|
||||
var shot = _random.NextFloat(1, 3.5f);
|
||||
_playContinues = shot > 2;
|
||||
|
||||
if (shot <= 2)
|
||||
{
|
||||
Resolve("Jump shot.", _defense / 8)
|
||||
.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."));
|
||||
|
||||
_io.WriteLine();
|
||||
ResolveJumpShot(scoreboard);
|
||||
}
|
||||
|
||||
_playContinues |= shot > 2;
|
||||
|
||||
while (_playContinues)
|
||||
{
|
||||
_playContinues = false;
|
||||
|
||||
Resolve(shot > 3 ? "Set shot." : "Lay up.", _defense / 7)
|
||||
.Do(0.413f, () => scoreboard.AddBasket("Shot is good."))
|
||||
.Or(() => ResolveBadShot(scoreboard, "Shot is missed.", 6 / _defense));
|
||||
_io.WriteLine();
|
||||
ResolveLayupOrSetShot(scoreboard, shot);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ResolveJumpShot(Scoreboard scoreboard)
|
||||
{
|
||||
Resolve("Jump shot.", _defense / 8)
|
||||
.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."));
|
||||
_io.WriteLine();
|
||||
}
|
||||
|
||||
private void ResolveLayupOrSetShot(Scoreboard scoreboard, float shot)
|
||||
{
|
||||
_playContinues = false;
|
||||
|
||||
Resolve(shot > 3 ? "Set shot." : "Lay up.", _defense / 7)
|
||||
.Do(0.413f, () => scoreboard.AddBasket("Shot is good."))
|
||||
.Or(() => ResolveBadShot(scoreboard, "Shot is missed.", 6 / _defense));
|
||||
_io.WriteLine();
|
||||
}
|
||||
|
||||
void ResolveBadShot(Scoreboard scoreboard, string message, float defenseFactor) =>
|
||||
Resolve(message, defenseFactor)
|
||||
.Do(0.5f, () => scoreboard.Turnover("Dartmouth controls the rebound."))
|
||||
|
||||
Reference in New Issue
Block a user