mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
Add Photon Tubes
This commit is contained in:
@@ -79,15 +79,14 @@ namespace SuperStarTrek
|
||||
_galaxy = new Galaxy();
|
||||
_initialKlingonCount = _galaxy.KlingonCount;
|
||||
|
||||
_enterprise = new Enterprise(3000, random.GetCoordinate(), _output);
|
||||
_enterprise = new Enterprise(3000, random.GetCoordinate(), _output, random);
|
||||
_enterprise
|
||||
.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
|
||||
.Add(new LongRangeSensors(_galaxy, _output))
|
||||
.Add(new PhotonTubes(10, _enterprise, _output, _input))
|
||||
.Add(new ShieldControl(_enterprise, _output, _input))
|
||||
.Add(new DamageControl(_enterprise, _output));
|
||||
|
||||
var quadrant = new Quadrant(_galaxy[_currentQuadrant], _enterprise);
|
||||
|
||||
_output.Write(Strings.Enterprise);
|
||||
_output.Write(
|
||||
Strings.Orders,
|
||||
@@ -100,6 +99,7 @@ namespace SuperStarTrek
|
||||
|
||||
_input.WaitForAnyKeyButEnter("when ready to accept command");
|
||||
|
||||
var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy);
|
||||
_enterprise.Enter(quadrant, Strings.StartText);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace SuperStarTrek
|
||||
return Console.ReadLine();
|
||||
}
|
||||
|
||||
public double GetNumber(string prompt)
|
||||
public float GetNumber(string prompt)
|
||||
{
|
||||
_output.Prompt(prompt);
|
||||
|
||||
while (true)
|
||||
{
|
||||
var response = Console.ReadLine();
|
||||
if (double.TryParse(response, out var value))
|
||||
if (float.TryParse(response, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace SuperStarTrek
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetNumber(string prompt, double minValue, double maxValue, out double value)
|
||||
public bool TryGetNumber(string prompt, float minValue, float maxValue, out float value)
|
||||
{
|
||||
value = GetNumber($"{prompt} ({minValue}-{maxValue})");
|
||||
|
||||
|
||||
@@ -15,9 +15,10 @@ namespace SuperStarTrek.Objects
|
||||
private readonly Output _output;
|
||||
private readonly List<Subsystem> _systems;
|
||||
private readonly Dictionary<Command, Subsystem> _commandExecutors;
|
||||
private readonly Random _random;
|
||||
private Quadrant _quadrant;
|
||||
|
||||
public Enterprise(int maxEnergy, Coordinates sector, Output output)
|
||||
public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random)
|
||||
{
|
||||
Sector = sector;
|
||||
TotalEnergy = _maxEnergy = maxEnergy;
|
||||
@@ -25,6 +26,7 @@ namespace SuperStarTrek.Objects
|
||||
_systems = new List<Subsystem>();
|
||||
_commandExecutors = new Dictionary<Command, Subsystem>();
|
||||
_output = output;
|
||||
_random = random;
|
||||
}
|
||||
|
||||
public Coordinates Quadrant => _quadrant.Coordinates;
|
||||
@@ -88,5 +90,37 @@ namespace SuperStarTrek.Objects
|
||||
}
|
||||
|
||||
public override string ToString() => "<*>";
|
||||
|
||||
internal CommandResult TakeHit(Coordinates sector, int hitStrength)
|
||||
{
|
||||
_output.WriteLine($"{hitStrength} unit hit on Enterprise from sector {sector}");
|
||||
ShieldControl.AbsorbHit(hitStrength);
|
||||
|
||||
if (ShieldControl.ShieldEnergy <= 0)
|
||||
{
|
||||
_output.WriteLine(Strings.Destroyed);
|
||||
return CommandResult.GameOver;
|
||||
}
|
||||
|
||||
_output.WriteLine($" <Shields down to {ShieldControl.ShieldEnergy} units>");
|
||||
|
||||
if (hitStrength >= 20)
|
||||
{
|
||||
TakeDamage(hitStrength);
|
||||
}
|
||||
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
private void TakeDamage(double hitStrength)
|
||||
{
|
||||
var hitShieldRatio = hitStrength / ShieldControl.ShieldEnergy;
|
||||
if (_random.GetDouble() > 0.6 || hitShieldRatio <= 0.02)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_systems[_random.Get1To8Inclusive() - 1].TakeDamage(hitShieldRatio + 0.5 * _random.GetDouble());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
using SuperStarTrek.Commands;
|
||||
using SuperStarTrek.Space;
|
||||
|
||||
namespace SuperStarTrek.Objects
|
||||
{
|
||||
internal class Klingon
|
||||
{
|
||||
private double _energy;
|
||||
private Coordinates _sector;
|
||||
private readonly Random _random;
|
||||
|
||||
public Klingon()
|
||||
public Klingon(Coordinates sector, Random random)
|
||||
{
|
||||
_energy = new Random().GetDouble(100, 300);
|
||||
_sector = sector;
|
||||
_random = random;
|
||||
_energy = _random.GetDouble(100, 300);
|
||||
}
|
||||
|
||||
public override string ToString() => "+K+";
|
||||
|
||||
public CommandResult FireOn(Enterprise enterprise)
|
||||
{
|
||||
var attackStrength = _random.GetDouble();
|
||||
var hitStrength = (int)(_energy * (2 + attackStrength) / _sector.GetDistanceTo(enterprise.Sector));
|
||||
_energy /= 3 + attackStrength;
|
||||
|
||||
return enterprise.TakeHit(_sector, hitStrength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ namespace SuperStarTrek.Objects
|
||||
private readonly Output _output;
|
||||
private readonly double _repairDelay;
|
||||
|
||||
public Starbase(Random random, Input input)
|
||||
public Starbase(Random random, Input input, Output output)
|
||||
{
|
||||
_repairDelay = random.GetDouble() * 0.5;
|
||||
_input = input;
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public override string ToString() => ">!<";
|
||||
@@ -34,5 +35,7 @@ namespace SuperStarTrek.Objects
|
||||
repairTime = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void ProtectEnterprise() => _output.WriteLine(Strings.Protected);
|
||||
}
|
||||
}
|
||||
|
||||
3
84 Super Star Trek/csharp/Resources/CourtMartial.txt
Normal file
3
84 Super Star Trek/csharp/Resources/CourtMartial.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
Starfleet Command reviewing your record to consider
|
||||
court martial!
|
||||
1
84 Super Star Trek/csharp/Resources/Protected.txt
Normal file
1
84 Super Star Trek/csharp/Resources/Protected.txt
Normal file
@@ -0,0 +1 @@
|
||||
Starbase shields protect the Enterprise
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
That does it, Captain!! You are hereby relieved of command
|
||||
and sentenced to 99 stardates at hard labor on Cygnus 12!!
|
||||
@@ -8,13 +8,16 @@ namespace SuperStarTrek.Resources
|
||||
{
|
||||
public static string CombatArea => GetResource();
|
||||
public static string Congratulations => GetResource();
|
||||
public static string CourtMartial => GetResource();
|
||||
public static string Destroyed => GetResource();
|
||||
public static string EndOfMission => GetResource();
|
||||
public static string Enterprise => GetResource();
|
||||
public static string Instructions => GetResource();
|
||||
public static string LowShields => GetResource();
|
||||
public static string Orders => GetResource();
|
||||
public static string Protected => GetResource();
|
||||
public static string RegionNames => GetResource();
|
||||
public static string RelievedOfCommand => GetResource();
|
||||
public static string RepairEstimate => GetResource();
|
||||
public static string RepairPrompt => GetResource();
|
||||
public static string ReplayPrompt => GetResource();
|
||||
|
||||
@@ -24,6 +24,34 @@ namespace SuperStarTrek.Space
|
||||
throw new ArgumentOutOfRangeException(argumentName, value, "Must be 0 to 7 inclusive");
|
||||
}
|
||||
|
||||
private static bool IsValid(int value) => value >= 0 && value <= 7;
|
||||
|
||||
public override string ToString() => $"{X+1} , {Y+1}";
|
||||
|
||||
internal void Deconstruct(out int x, out int y)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
|
||||
internal static bool TryCreate(float x, float y, out Coordinates coordinates)
|
||||
{
|
||||
var roundedX = Round(x);
|
||||
var roundedY = Round(y);
|
||||
|
||||
if (IsValid(roundedX) && IsValid(roundedY))
|
||||
{
|
||||
coordinates = new Coordinates(roundedX, roundedY);
|
||||
return true;
|
||||
}
|
||||
|
||||
coordinates = default;
|
||||
return false;
|
||||
|
||||
int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
internal float GetDistanceTo(Coordinates destination) =>
|
||||
(float)Math.Sqrt(Math.Pow(X - destination.X, 2) + Math.Pow(Y - destination.Y, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SuperStarTrek.Space
|
||||
{
|
||||
@@ -24,7 +25,7 @@ namespace SuperStarTrek.Space
|
||||
(0, 1)
|
||||
};
|
||||
|
||||
public Course(double direction)
|
||||
public Course(float direction)
|
||||
{
|
||||
if (direction < 1 || direction > 9)
|
||||
{
|
||||
@@ -44,7 +45,25 @@ namespace SuperStarTrek.Space
|
||||
DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
|
||||
}
|
||||
|
||||
public double DeltaX { get; }
|
||||
public double DeltaY { get; }
|
||||
public float DeltaX { get; }
|
||||
public float DeltaY { get; }
|
||||
|
||||
public IEnumerable<Coordinates> GetSectorsFrom(Coordinates start)
|
||||
{
|
||||
(double x, double y) = start;
|
||||
|
||||
while(true)
|
||||
{
|
||||
x += DeltaX;
|
||||
y += DeltaY;
|
||||
|
||||
if (!Coordinates.TryCreate(x, y, out var coordinates))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SuperStarTrek.Commands;
|
||||
using SuperStarTrek.Objects;
|
||||
using SuperStarTrek.Resources;
|
||||
|
||||
namespace SuperStarTrek.Space
|
||||
{
|
||||
@@ -10,43 +12,47 @@ namespace SuperStarTrek.Space
|
||||
private readonly QuadrantInfo _info;
|
||||
private readonly Random _random;
|
||||
private readonly Dictionary<Coordinates, object> _sectors;
|
||||
private readonly Coordinates _enterpriseSector;
|
||||
private readonly Enterprise _enterprise;
|
||||
private readonly Coordinates _starbaseSector;
|
||||
private readonly Galaxy _galaxy;
|
||||
|
||||
public Quadrant(QuadrantInfo info, Enterprise enterprise)
|
||||
public Quadrant(QuadrantInfo info, Enterprise enterprise, Random random, Galaxy galaxy)
|
||||
{
|
||||
_info = info;
|
||||
_random = new Random();
|
||||
_random = random;
|
||||
_galaxy = galaxy;
|
||||
|
||||
_enterpriseSector = enterprise.Sector;
|
||||
_sectors = new Dictionary<Coordinates, object> { [enterprise.Sector] = enterprise };
|
||||
PositionObject(() => new Klingon(), _info.KlingonCount);
|
||||
_sectors = new() { [enterprise.Sector] = _enterprise = enterprise };
|
||||
PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
|
||||
if (_info.HasStarbase)
|
||||
{
|
||||
_starbaseSector = PositionObject(() => new Starbase(_random, new Input(new Output())));
|
||||
_starbaseSector = PositionObject(_ => new Starbase(_random, new Input(new Output()), new Output()));
|
||||
}
|
||||
PositionObject(() => new Star(), _info.StarCount);
|
||||
PositionObject(_ => new Star(), _info.StarCount);
|
||||
}
|
||||
|
||||
public object this[Coordinates coordinates] => _sectors.GetValueOrDefault(coordinates);
|
||||
public Coordinates Coordinates => _info.Coordinates;
|
||||
public bool HasKlingons => _info.KlingonCount > 0;
|
||||
public bool HasStarbase => _info.HasStarbase;
|
||||
public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null;
|
||||
public bool EnterpriseIsNextToStarbase =>
|
||||
_info.HasStarbase &&
|
||||
Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 &&
|
||||
Math.Abs(_enterpriseSector.Y - _starbaseSector.Y) <= 1;
|
||||
Math.Abs(_enterprise.Sector.X - _starbaseSector.X) <= 1 &&
|
||||
Math.Abs(_enterprise.Sector.Y - _starbaseSector.Y) <= 1;
|
||||
|
||||
private IEnumerable<Klingon> Klingons => _sectors.Values.OfType<Klingon>();
|
||||
|
||||
public override string ToString() => _info.Name;
|
||||
|
||||
private Coordinates PositionObject(Func<object> objectFactory)
|
||||
private Coordinates PositionObject(Func<Coordinates, object> objectFactory)
|
||||
{
|
||||
var sector = GetRandomEmptySector();
|
||||
_sectors[sector] = objectFactory.Invoke();
|
||||
_sectors[sector] = objectFactory.Invoke(sector);
|
||||
return sector;
|
||||
}
|
||||
|
||||
private void PositionObject(Func<object> objectFactory, int count)
|
||||
private void PositionObject(Func<Coordinates, object> objectFactory, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
@@ -54,6 +60,54 @@ namespace SuperStarTrek.Space
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TorpedoCollisionAt(Coordinates coordinates, out string message, out bool gameOver)
|
||||
{
|
||||
gameOver = false;
|
||||
message = default;
|
||||
|
||||
switch (_sectors.GetValueOrDefault(coordinates))
|
||||
{
|
||||
case Klingon _:
|
||||
_sectors.Remove(coordinates);
|
||||
_info.RemoveKlingon();
|
||||
message = "*** Klingon destroyed ***";
|
||||
gameOver = _galaxy.KlingonCount == 0;
|
||||
return true;
|
||||
|
||||
case Star _:
|
||||
message = $"Star at {coordinates} absorbed torpedo energy.";
|
||||
return true;
|
||||
|
||||
case Starbase _:
|
||||
_sectors.Remove(coordinates);
|
||||
_info.RemoveStarbase();
|
||||
message = "*** Starbase destroyed ***" +
|
||||
(_galaxy.StarbaseCount > 0 ? Strings.CourtMartial : Strings.RelievedOfCommand);
|
||||
gameOver = _galaxy.StarbaseCount == 0;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal CommandResult KlingonsFireOnEnterprise()
|
||||
{
|
||||
if (EnterpriseIsNextToStarbase && Klingons.Any())
|
||||
{
|
||||
Starbase.ProtectEnterprise();
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
foreach (var klingon in Klingons)
|
||||
{
|
||||
var result = klingon.FireOn(_enterprise);
|
||||
if (result.IsGameOver) { return result; }
|
||||
}
|
||||
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
private Coordinates GetRandomEmptySector()
|
||||
{
|
||||
while (true)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using SuperStarTrek.Objects;
|
||||
|
||||
namespace SuperStarTrek.Space
|
||||
{
|
||||
internal class QuadrantInfo
|
||||
@@ -39,12 +41,25 @@ namespace SuperStarTrek.Space
|
||||
|
||||
internal void AddStarbase() => HasStarbase = true;
|
||||
|
||||
public string Scan()
|
||||
internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy) =>
|
||||
new(this, enterprise, random, galaxy);
|
||||
|
||||
internal string Scan()
|
||||
{
|
||||
_isKnown = true;
|
||||
return ToString();
|
||||
}
|
||||
|
||||
public override string ToString() => _isKnown ? $"{KlingonCount}{(HasStarbase ? 1 : 0)}{StarCount}" : "***";
|
||||
|
||||
internal void RemoveKlingon()
|
||||
{
|
||||
if (KlingonCount > 0)
|
||||
{
|
||||
KlingonCount -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveStarbase() => HasStarbase = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@ namespace SuperStarTrek.Systems
|
||||
private readonly Output _output;
|
||||
|
||||
public DamageControl(Enterprise enterprise, Output output)
|
||||
: base("Damage Control", Command.DAM)
|
||||
: base("Damage Control", Command.DAM, output)
|
||||
{
|
||||
_enterprise = enterprise;
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
||||
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||
{
|
||||
if (IsDamaged)
|
||||
{
|
||||
|
||||
@@ -15,19 +15,15 @@ namespace SuperStarTrek.Systems
|
||||
private readonly Output _output;
|
||||
|
||||
public LongRangeSensors(Galaxy galaxy, Output output)
|
||||
: base("Long Range Sensors", Command.LRS)
|
||||
: base("Long Range Sensors", Command.LRS, output)
|
||||
{
|
||||
_galaxy = galaxy;
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
||||
{
|
||||
if (Condition < 0)
|
||||
{
|
||||
_output.WriteLine("Long Range Sensors are inoperable");
|
||||
}
|
||||
else
|
||||
protected override bool CanExecuteCommand() => IsOperational("{name} are inoperable");
|
||||
|
||||
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||
{
|
||||
_output.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}");
|
||||
_output.WriteLine("-------------------");
|
||||
@@ -36,7 +32,6 @@ namespace SuperStarTrek.Systems
|
||||
_output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
|
||||
_output.WriteLine("-------------------");
|
||||
}
|
||||
}
|
||||
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
63
84 Super Star Trek/csharp/Systems/PhotonTubes.cs
Normal file
63
84 Super Star Trek/csharp/Systems/PhotonTubes.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using SuperStarTrek.Commands;
|
||||
using SuperStarTrek.Objects;
|
||||
using SuperStarTrek.Space;
|
||||
|
||||
namespace SuperStarTrek.Systems
|
||||
{
|
||||
internal class PhotonTubes : Subsystem
|
||||
{
|
||||
private readonly int _tubeCount;
|
||||
private readonly Enterprise _enterprise;
|
||||
private readonly Output _output;
|
||||
private readonly Input _input;
|
||||
|
||||
public PhotonTubes(int tubeCount, Enterprise enterprise, Output output, Input input)
|
||||
: base("Photon Tubes", Command.TOR, output)
|
||||
{
|
||||
TorpedoCount = _tubeCount = tubeCount;
|
||||
_enterprise = enterprise;
|
||||
_output = output;
|
||||
_input = input;
|
||||
}
|
||||
|
||||
public int TorpedoCount { get; private set; }
|
||||
|
||||
protected override bool CanExecuteCommand() => HasTorpedoes() && IsOperational("{name} are not operational");
|
||||
|
||||
private bool HasTorpedoes()
|
||||
{
|
||||
if (TorpedoCount > 0) { return true; }
|
||||
|
||||
_output.WriteLine("All photon torpedoes expended");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||
{
|
||||
if (!_input.TryGetNumber("Photon torpedo course", 1, 9, out var direction))
|
||||
{
|
||||
_output.WriteLine("Ensign Chekov reports, 'Incorrect course data, sir!'");
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
var isHit = false;
|
||||
_output.WriteLine("Torpedo track:");
|
||||
foreach (var sector in new Course(direction).GetSectorsFrom(_enterprise.Sector))
|
||||
{
|
||||
_output.WriteLine($" {sector}");
|
||||
|
||||
if (quadrant.TorpedoCollisionAt(sector, out var message, out var gameOver))
|
||||
{
|
||||
_output.WriteLine(message);
|
||||
isHit = true;
|
||||
if (gameOver) { return CommandResult.GameOver; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isHit) { _output.WriteLine("Torpedo missed!"); }
|
||||
|
||||
return quadrant.KlingonsFireOnEnterprise();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace SuperStarTrek.Systems
|
||||
private readonly Input _input;
|
||||
|
||||
public ShieldControl(Enterprise enterprise, Output output, Input input)
|
||||
: base("Shield Control", Command.SHE)
|
||||
: base("Shield Control", Command.SHE, output)
|
||||
{
|
||||
_enterprise = enterprise;
|
||||
_output = output;
|
||||
@@ -20,21 +20,9 @@ namespace SuperStarTrek.Systems
|
||||
|
||||
public double ShieldEnergy { get; private set; }
|
||||
|
||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
||||
{
|
||||
if (Condition < 0)
|
||||
{
|
||||
_output.WriteLine("Shield Control inoperable");
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateShields();
|
||||
}
|
||||
protected override bool CanExecuteCommand() => IsOperational("{name} inoperable");
|
||||
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
private void UpdateShields()
|
||||
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||
{
|
||||
_output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
|
||||
var requested = _input.GetNumber($"Number of units to shields");
|
||||
@@ -47,6 +35,8 @@ namespace SuperStarTrek.Systems
|
||||
{
|
||||
_output.WriteLine("<SHIELDS UNCHANGED>");
|
||||
}
|
||||
|
||||
return CommandResult.Ok;
|
||||
}
|
||||
|
||||
private bool Validate(double requested)
|
||||
@@ -59,5 +49,7 @@ namespace SuperStarTrek.Systems
|
||||
|
||||
return requested >= 0 && requested != ShieldEnergy;
|
||||
}
|
||||
|
||||
internal void AbsorbHit(int hitStrength) => ShieldEnergy -= hitStrength;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace SuperStarTrek.Systems
|
||||
private readonly Output _output;
|
||||
|
||||
public ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, Output output)
|
||||
: base("Short Range Sensors", Command.SRS)
|
||||
: base("Short Range Sensors", Command.SRS, output)
|
||||
{
|
||||
_enterprise = enterprise;
|
||||
_galaxy = galaxy;
|
||||
@@ -25,7 +25,7 @@ namespace SuperStarTrek.Systems
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
||||
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||
{
|
||||
if (_enterprise.IsDocked)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using SuperStarTrek.Commands;
|
||||
using SuperStarTrek.Space;
|
||||
|
||||
@@ -5,11 +6,14 @@ namespace SuperStarTrek.Systems
|
||||
{
|
||||
internal abstract class Subsystem
|
||||
{
|
||||
protected Subsystem(string name, Command command)
|
||||
private readonly Output _output;
|
||||
|
||||
protected Subsystem(string name, Command command, Output output)
|
||||
{
|
||||
Name = name;
|
||||
Command = command;
|
||||
Condition = 0;
|
||||
_output = output;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
@@ -17,10 +21,33 @@ namespace SuperStarTrek.Systems
|
||||
public bool IsDamaged => Condition < 0;
|
||||
public Command Command { get; }
|
||||
|
||||
public abstract CommandResult ExecuteCommand(Quadrant quadrant);
|
||||
public void Repair()
|
||||
protected virtual bool CanExecuteCommand() => true;
|
||||
|
||||
protected bool IsOperational(string notOperationalMessage)
|
||||
{
|
||||
if (Condition < 0) { Condition = 0; }
|
||||
if (IsDamaged)
|
||||
{
|
||||
_output.WriteLine(notOperationalMessage.Replace("{name}", Name));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public CommandResult ExecuteCommand(Quadrant quadrant)
|
||||
=> CanExecuteCommand() ? ExecuteCommandCore(quadrant) : CommandResult.Ok;
|
||||
|
||||
protected abstract CommandResult ExecuteCommandCore(Quadrant quadrant);
|
||||
|
||||
public virtual void Repair()
|
||||
{
|
||||
if (IsDamaged) { Condition = 0; }
|
||||
}
|
||||
|
||||
internal void TakeDamage(double damage)
|
||||
{
|
||||
Condition -= damage;
|
||||
_output.WriteLine($"Damage Control reports, '{Name} damaged by the hit.'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user