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();
|
_galaxy = new Galaxy();
|
||||||
_initialKlingonCount = _galaxy.KlingonCount;
|
_initialKlingonCount = _galaxy.KlingonCount;
|
||||||
|
|
||||||
_enterprise = new Enterprise(3000, random.GetCoordinate(), _output);
|
_enterprise = new Enterprise(3000, random.GetCoordinate(), _output, random);
|
||||||
_enterprise
|
_enterprise
|
||||||
.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
|
.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
|
||||||
.Add(new LongRangeSensors(_galaxy, _output))
|
.Add(new LongRangeSensors(_galaxy, _output))
|
||||||
|
.Add(new PhotonTubes(10, _enterprise, _output, _input))
|
||||||
.Add(new ShieldControl(_enterprise, _output, _input))
|
.Add(new ShieldControl(_enterprise, _output, _input))
|
||||||
.Add(new DamageControl(_enterprise, _output));
|
.Add(new DamageControl(_enterprise, _output));
|
||||||
|
|
||||||
var quadrant = new Quadrant(_galaxy[_currentQuadrant], _enterprise);
|
|
||||||
|
|
||||||
_output.Write(Strings.Enterprise);
|
_output.Write(Strings.Enterprise);
|
||||||
_output.Write(
|
_output.Write(
|
||||||
Strings.Orders,
|
Strings.Orders,
|
||||||
@@ -100,6 +99,7 @@ namespace SuperStarTrek
|
|||||||
|
|
||||||
_input.WaitForAnyKeyButEnter("when ready to accept command");
|
_input.WaitForAnyKeyButEnter("when ready to accept command");
|
||||||
|
|
||||||
|
var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy);
|
||||||
_enterprise.Enter(quadrant, Strings.StartText);
|
_enterprise.Enter(quadrant, Strings.StartText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ namespace SuperStarTrek
|
|||||||
return Console.ReadLine();
|
return Console.ReadLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetNumber(string prompt)
|
public float GetNumber(string prompt)
|
||||||
{
|
{
|
||||||
_output.Prompt(prompt);
|
_output.Prompt(prompt);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var response = Console.ReadLine();
|
var response = Console.ReadLine();
|
||||||
if (double.TryParse(response, out var value))
|
if (float.TryParse(response, out var value))
|
||||||
{
|
{
|
||||||
return 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})");
|
value = GetNumber($"{prompt} ({minValue}-{maxValue})");
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,10 @@ namespace SuperStarTrek.Objects
|
|||||||
private readonly Output _output;
|
private readonly Output _output;
|
||||||
private readonly List<Subsystem> _systems;
|
private readonly List<Subsystem> _systems;
|
||||||
private readonly Dictionary<Command, Subsystem> _commandExecutors;
|
private readonly Dictionary<Command, Subsystem> _commandExecutors;
|
||||||
|
private readonly Random _random;
|
||||||
private Quadrant _quadrant;
|
private Quadrant _quadrant;
|
||||||
|
|
||||||
public Enterprise(int maxEnergy, Coordinates sector, Output output)
|
public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random)
|
||||||
{
|
{
|
||||||
Sector = sector;
|
Sector = sector;
|
||||||
TotalEnergy = _maxEnergy = maxEnergy;
|
TotalEnergy = _maxEnergy = maxEnergy;
|
||||||
@@ -25,6 +26,7 @@ namespace SuperStarTrek.Objects
|
|||||||
_systems = new List<Subsystem>();
|
_systems = new List<Subsystem>();
|
||||||
_commandExecutors = new Dictionary<Command, Subsystem>();
|
_commandExecutors = new Dictionary<Command, Subsystem>();
|
||||||
_output = output;
|
_output = output;
|
||||||
|
_random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Coordinates Quadrant => _quadrant.Coordinates;
|
public Coordinates Quadrant => _quadrant.Coordinates;
|
||||||
@@ -88,5 +90,37 @@ namespace SuperStarTrek.Objects
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => "<*>";
|
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
|
namespace SuperStarTrek.Objects
|
||||||
{
|
{
|
||||||
internal class Klingon
|
internal class Klingon
|
||||||
{
|
{
|
||||||
private double _energy;
|
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 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 Output _output;
|
||||||
private readonly double _repairDelay;
|
private readonly double _repairDelay;
|
||||||
|
|
||||||
public Starbase(Random random, Input input)
|
public Starbase(Random random, Input input, Output output)
|
||||||
{
|
{
|
||||||
_repairDelay = random.GetDouble() * 0.5;
|
_repairDelay = random.GetDouble() * 0.5;
|
||||||
_input = input;
|
_input = input;
|
||||||
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => ">!<";
|
public override string ToString() => ">!<";
|
||||||
@@ -34,5 +35,7 @@ namespace SuperStarTrek.Objects
|
|||||||
repairTime = 0;
|
repairTime = 0;
|
||||||
return false;
|
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 CombatArea => GetResource();
|
||||||
public static string Congratulations => GetResource();
|
public static string Congratulations => GetResource();
|
||||||
|
public static string CourtMartial => GetResource();
|
||||||
public static string Destroyed => GetResource();
|
public static string Destroyed => GetResource();
|
||||||
public static string EndOfMission => GetResource();
|
public static string EndOfMission => GetResource();
|
||||||
public static string Enterprise => GetResource();
|
public static string Enterprise => GetResource();
|
||||||
public static string Instructions => GetResource();
|
public static string Instructions => GetResource();
|
||||||
public static string LowShields => GetResource();
|
public static string LowShields => GetResource();
|
||||||
public static string Orders => GetResource();
|
public static string Orders => GetResource();
|
||||||
|
public static string Protected => GetResource();
|
||||||
public static string RegionNames => GetResource();
|
public static string RegionNames => GetResource();
|
||||||
|
public static string RelievedOfCommand => GetResource();
|
||||||
public static string RepairEstimate => GetResource();
|
public static string RepairEstimate => GetResource();
|
||||||
public static string RepairPrompt => GetResource();
|
public static string RepairPrompt => GetResource();
|
||||||
public static string ReplayPrompt => GetResource();
|
public static string ReplayPrompt => GetResource();
|
||||||
|
|||||||
@@ -24,6 +24,34 @@ namespace SuperStarTrek.Space
|
|||||||
throw new ArgumentOutOfRangeException(argumentName, value, "Must be 0 to 7 inclusive");
|
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}";
|
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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace SuperStarTrek.Space
|
namespace SuperStarTrek.Space
|
||||||
{
|
{
|
||||||
@@ -24,7 +25,7 @@ namespace SuperStarTrek.Space
|
|||||||
(0, 1)
|
(0, 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
public Course(double direction)
|
public Course(float direction)
|
||||||
{
|
{
|
||||||
if (direction < 1 || direction > 9)
|
if (direction < 1 || direction > 9)
|
||||||
{
|
{
|
||||||
@@ -44,7 +45,25 @@ namespace SuperStarTrek.Space
|
|||||||
DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
|
DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double DeltaX { get; }
|
public float DeltaX { get; }
|
||||||
public double DeltaY { 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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using SuperStarTrek.Commands;
|
||||||
using SuperStarTrek.Objects;
|
using SuperStarTrek.Objects;
|
||||||
|
using SuperStarTrek.Resources;
|
||||||
|
|
||||||
namespace SuperStarTrek.Space
|
namespace SuperStarTrek.Space
|
||||||
{
|
{
|
||||||
@@ -10,43 +12,47 @@ namespace SuperStarTrek.Space
|
|||||||
private readonly QuadrantInfo _info;
|
private readonly QuadrantInfo _info;
|
||||||
private readonly Random _random;
|
private readonly Random _random;
|
||||||
private readonly Dictionary<Coordinates, object> _sectors;
|
private readonly Dictionary<Coordinates, object> _sectors;
|
||||||
private readonly Coordinates _enterpriseSector;
|
private readonly Enterprise _enterprise;
|
||||||
private readonly Coordinates _starbaseSector;
|
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;
|
_info = info;
|
||||||
_random = new Random();
|
_random = random;
|
||||||
|
_galaxy = galaxy;
|
||||||
|
|
||||||
_enterpriseSector = enterprise.Sector;
|
_sectors = new() { [enterprise.Sector] = _enterprise = enterprise };
|
||||||
_sectors = new Dictionary<Coordinates, object> { [enterprise.Sector] = enterprise };
|
PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
|
||||||
PositionObject(() => new Klingon(), _info.KlingonCount);
|
|
||||||
if (_info.HasStarbase)
|
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 Coordinates Coordinates => _info.Coordinates;
|
||||||
public bool HasKlingons => _info.KlingonCount > 0;
|
public bool HasKlingons => _info.KlingonCount > 0;
|
||||||
public bool HasStarbase => _info.HasStarbase;
|
public bool HasStarbase => _info.HasStarbase;
|
||||||
public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null;
|
public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null;
|
||||||
public bool EnterpriseIsNextToStarbase =>
|
public bool EnterpriseIsNextToStarbase =>
|
||||||
_info.HasStarbase &&
|
_info.HasStarbase &&
|
||||||
Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 &&
|
Math.Abs(_enterprise.Sector.X - _starbaseSector.X) <= 1 &&
|
||||||
Math.Abs(_enterpriseSector.Y - _starbaseSector.Y) <= 1;
|
Math.Abs(_enterprise.Sector.Y - _starbaseSector.Y) <= 1;
|
||||||
|
|
||||||
|
private IEnumerable<Klingon> Klingons => _sectors.Values.OfType<Klingon>();
|
||||||
|
|
||||||
public override string ToString() => _info.Name;
|
public override string ToString() => _info.Name;
|
||||||
|
|
||||||
private Coordinates PositionObject(Func<object> objectFactory)
|
private Coordinates PositionObject(Func<Coordinates, object> objectFactory)
|
||||||
{
|
{
|
||||||
var sector = GetRandomEmptySector();
|
var sector = GetRandomEmptySector();
|
||||||
_sectors[sector] = objectFactory.Invoke();
|
_sectors[sector] = objectFactory.Invoke(sector);
|
||||||
return 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++)
|
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()
|
private Coordinates GetRandomEmptySector()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using SuperStarTrek.Objects;
|
||||||
|
|
||||||
namespace SuperStarTrek.Space
|
namespace SuperStarTrek.Space
|
||||||
{
|
{
|
||||||
internal class QuadrantInfo
|
internal class QuadrantInfo
|
||||||
@@ -39,12 +41,25 @@ namespace SuperStarTrek.Space
|
|||||||
|
|
||||||
internal void AddStarbase() => HasStarbase = true;
|
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;
|
_isKnown = true;
|
||||||
return ToString();
|
return ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => _isKnown ? $"{KlingonCount}{(HasStarbase ? 1 : 0)}{StarCount}" : "***";
|
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;
|
private readonly Output _output;
|
||||||
|
|
||||||
public DamageControl(Enterprise enterprise, Output output)
|
public DamageControl(Enterprise enterprise, Output output)
|
||||||
: base("Damage Control", Command.DAM)
|
: base("Damage Control", Command.DAM, output)
|
||||||
{
|
{
|
||||||
_enterprise = enterprise;
|
_enterprise = enterprise;
|
||||||
_output = output;
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||||
{
|
{
|
||||||
if (IsDamaged)
|
if (IsDamaged)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,27 +15,22 @@ namespace SuperStarTrek.Systems
|
|||||||
private readonly Output _output;
|
private readonly Output _output;
|
||||||
|
|
||||||
public LongRangeSensors(Galaxy galaxy, Output output)
|
public LongRangeSensors(Galaxy galaxy, Output output)
|
||||||
: base("Long Range Sensors", Command.LRS)
|
: base("Long Range Sensors", Command.LRS, output)
|
||||||
{
|
{
|
||||||
_galaxy = galaxy;
|
_galaxy = galaxy;
|
||||||
_output = output;
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
protected override bool CanExecuteCommand() => IsOperational("{name} are inoperable");
|
||||||
|
|
||||||
|
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||||
{
|
{
|
||||||
if (Condition < 0)
|
_output.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}");
|
||||||
|
_output.WriteLine("-------------------");
|
||||||
|
foreach (var quadrants in _galaxy.GetNeighborhood(quadrant))
|
||||||
{
|
{
|
||||||
_output.WriteLine("Long Range Sensors are inoperable");
|
_output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_output.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}");
|
|
||||||
_output.WriteLine("-------------------");
|
_output.WriteLine("-------------------");
|
||||||
foreach (var quadrants in _galaxy.GetNeighborhood(quadrant))
|
|
||||||
{
|
|
||||||
_output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
|
|
||||||
_output.WriteLine("-------------------");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandResult.Ok;
|
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;
|
private readonly Input _input;
|
||||||
|
|
||||||
public ShieldControl(Enterprise enterprise, Output output, Input input)
|
public ShieldControl(Enterprise enterprise, Output output, Input input)
|
||||||
: base("Shield Control", Command.SHE)
|
: base("Shield Control", Command.SHE, output)
|
||||||
{
|
{
|
||||||
_enterprise = enterprise;
|
_enterprise = enterprise;
|
||||||
_output = output;
|
_output = output;
|
||||||
@@ -20,21 +20,9 @@ namespace SuperStarTrek.Systems
|
|||||||
|
|
||||||
public double ShieldEnergy { get; private set; }
|
public double ShieldEnergy { get; private set; }
|
||||||
|
|
||||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
protected override bool CanExecuteCommand() => IsOperational("{name} inoperable");
|
||||||
{
|
|
||||||
if (Condition < 0)
|
|
||||||
{
|
|
||||||
_output.WriteLine("Shield Control inoperable");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateShields();
|
|
||||||
}
|
|
||||||
|
|
||||||
return CommandResult.Ok;
|
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateShields()
|
|
||||||
{
|
{
|
||||||
_output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
|
_output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
|
||||||
var requested = _input.GetNumber($"Number of units to shields");
|
var requested = _input.GetNumber($"Number of units to shields");
|
||||||
@@ -47,6 +35,8 @@ namespace SuperStarTrek.Systems
|
|||||||
{
|
{
|
||||||
_output.WriteLine("<SHIELDS UNCHANGED>");
|
_output.WriteLine("<SHIELDS UNCHANGED>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return CommandResult.Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Validate(double requested)
|
private bool Validate(double requested)
|
||||||
@@ -59,5 +49,7 @@ namespace SuperStarTrek.Systems
|
|||||||
|
|
||||||
return requested >= 0 && requested != ShieldEnergy;
|
return requested >= 0 && requested != ShieldEnergy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AbsorbHit(int hitStrength) => ShieldEnergy -= hitStrength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace SuperStarTrek.Systems
|
|||||||
private readonly Output _output;
|
private readonly Output _output;
|
||||||
|
|
||||||
public ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, 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;
|
_enterprise = enterprise;
|
||||||
_galaxy = galaxy;
|
_galaxy = galaxy;
|
||||||
@@ -25,7 +25,7 @@ namespace SuperStarTrek.Systems
|
|||||||
_output = output;
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CommandResult ExecuteCommand(Quadrant quadrant)
|
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
|
||||||
{
|
{
|
||||||
if (_enterprise.IsDocked)
|
if (_enterprise.IsDocked)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using SuperStarTrek.Commands;
|
using SuperStarTrek.Commands;
|
||||||
using SuperStarTrek.Space;
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
@@ -5,11 +6,14 @@ namespace SuperStarTrek.Systems
|
|||||||
{
|
{
|
||||||
internal abstract class Subsystem
|
internal abstract class Subsystem
|
||||||
{
|
{
|
||||||
protected Subsystem(string name, Command command)
|
private readonly Output _output;
|
||||||
|
|
||||||
|
protected Subsystem(string name, Command command, Output output)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Command = command;
|
Command = command;
|
||||||
Condition = 0;
|
Condition = 0;
|
||||||
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
@@ -17,10 +21,33 @@ namespace SuperStarTrek.Systems
|
|||||||
public bool IsDamaged => Condition < 0;
|
public bool IsDamaged => Condition < 0;
|
||||||
public Command Command { get; }
|
public Command Command { get; }
|
||||||
|
|
||||||
public abstract CommandResult ExecuteCommand(Quadrant quadrant);
|
protected virtual bool CanExecuteCommand() => true;
|
||||||
public void Repair()
|
|
||||||
|
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