Add Damage Control

This commit is contained in:
Andrew Cooper
2021-03-01 22:53:22 +11:00
parent 4d1a9176ec
commit 8c397ea8f9
19 changed files with 200 additions and 36 deletions

View File

@@ -33,11 +33,7 @@ namespace SuperStarTrek
{ {
_output.Write(Strings.Title); _output.Write(Strings.Title);
_output.Write("Do you need instructions (Y/N)? "); if (_input.GetYesNo("Do you need instructions", Input.YesNoMode.FalseOnN))
var response = Console.ReadLine();
_output.WriteLine();
if (!response.Equals("N", InvariantCultureIgnoreCase))
{ {
_output.Write(Strings.Instructions); _output.Write(Strings.Instructions);
@@ -68,7 +64,16 @@ namespace SuperStarTrek
{ {
var command = _input.GetCommand(); var command = _input.GetCommand();
gameOver = command == Command.XXX || _enterprise.Execute(command); gameOver = command == Command.XXX || _enterprise.Execute(command) || CheckIfStranded();
}
if (_galaxy.KlingonCount > 0)
{
_output.Write(Strings.EndOfMission, _currentStardate, _galaxy.KlingonCount);
}
else
{
_output.Write(Strings.Congratulations, GetEfficiency());
} }
} }
@@ -86,12 +91,29 @@ namespace SuperStarTrek
_initialKlingonCount = _galaxy.KlingonCount; _initialKlingonCount = _galaxy.KlingonCount;
_enterprise = new Enterprise(3000, random.GetCoordinate()); _enterprise = new Enterprise(3000, random.GetCoordinate());
_enterprise.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) _enterprise
.Add(new ShieldControl(_enterprise, _output, _input)); .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
.Add(new ShieldControl(_enterprise, _output, _input))
.Add(new DamageControl(_enterprise, _output));
return new Quadrant(_galaxy[_currentQuadrant], _enterprise); return new Quadrant(_galaxy[_currentQuadrant], _enterprise);
} }
public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye"); public bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye");
private bool CheckIfStranded()
{
if (_enterprise.TotalEnergy < 10 ||
_enterprise.Energy < 10 && _enterprise.Shields.IsDamaged)
{
_output.Write(Strings.Stranded);
return true;
}
return false;
}
private double GetEfficiency() =>
1000 * Math.Pow(_initialKlingonCount / (_currentStardate - _initialStardate), 2);
} }
} }

View File

@@ -72,5 +72,26 @@ namespace SuperStarTrek
_output.WriteLine(); _output.WriteLine();
} }
} }
public bool GetYesNo(string prompt, YesNoMode mode)
{
_output.Prompt($"{prompt} (Y/N)");
var response = Console.ReadLine().ToUpperInvariant();
return (mode, response) switch
{
(YesNoMode.FalseOnN, "N") => false,
(YesNoMode.FalseOnN, _) => true,
(YesNoMode.TrueOnY, "Y") => true,
(YesNoMode.TrueOnY, _) => false,
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, "Invalid value")
};
}
public enum YesNoMode
{
TrueOnY,
FalseOnN
}
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using SuperStarTrek.Resources; using SuperStarTrek.Resources;
using SuperStarTrek.Space; using SuperStarTrek.Space;
@@ -13,7 +14,6 @@ namespace SuperStarTrek.Objects
private readonly List<Subsystem> _systems; private readonly List<Subsystem> _systems;
private readonly Dictionary<Command, Subsystem> _commandExecutors; private readonly Dictionary<Command, Subsystem> _commandExecutors;
private Quadrant _quadrant; private Quadrant _quadrant;
private ShieldControl _shieldControl;
public Enterprise(int maxEnergy, Coordinates sector) public Enterprise(int maxEnergy, Coordinates sector)
{ {
@@ -27,11 +27,12 @@ namespace SuperStarTrek.Objects
public Coordinates Quadrant => _quadrant.Coordinates; public Coordinates Quadrant => _quadrant.Coordinates;
public Coordinates Sector { get; } public Coordinates Sector { get; }
public string Condition => GetCondition(); public string Condition => GetCondition();
public double Shields => _shieldControl.Energy; public ShieldControl Shields => (ShieldControl)_commandExecutors[Command.SHE];
public double Energy => TotalEnergy - Shields; public double Energy => TotalEnergy - Shields.Energy;
public double TotalEnergy { get; private set; } public double TotalEnergy { get; private set; }
public int DamagedSystemCount => _systems.Count(s => s.IsDamaged);
public IEnumerable<Subsystem> Systems => _systems;
public int TorpedoCount { get; } public int TorpedoCount { get; }
public bool IsDocked { get; private set; } public bool IsDocked { get; private set; }
public Enterprise Add(Subsystem system) public Enterprise Add(Subsystem system)
@@ -39,23 +40,9 @@ namespace SuperStarTrek.Objects
_systems.Add(system); _systems.Add(system);
_commandExecutors[system.Command] = system; _commandExecutors[system.Command] = system;
if (system is ShieldControl shieldControl) { _shieldControl = shieldControl; }
return this; return this;
} }
public string GetDamageReport()
{
var report = new StringBuilder();
report.AppendLine().AppendLine().AppendLine("Device State of Repair");
foreach (var system in _systems)
{
report.Append(system.Name.PadRight(25)).AppendLine(system.Condition.ToString(" 0.00;-0.00"));
}
report.AppendLine();
return report.ToString();
}
public void Enter(Quadrant quadrant, string entryTextFormat) public void Enter(Quadrant quadrant, string entryTextFormat)
{ {
_quadrant = quadrant; _quadrant = quadrant;
@@ -66,7 +53,7 @@ namespace SuperStarTrek.Objects
if (quadrant.HasKlingons) if (quadrant.HasKlingons)
{ {
_output.Write(Strings.CombatArea); _output.Write(Strings.CombatArea);
if (Shields <= 200) { _output.Write(Strings.LowShields); } if (Shields.Energy <= 200) { _output.Write(Strings.LowShields); }
} }
IsDocked = quadrant.EnterpriseIsNextToStarbase; IsDocked = quadrant.EnterpriseIsNextToStarbase;

View File

@@ -1,7 +1,38 @@
using SuperStarTrek.Resources;
namespace SuperStarTrek.Objects namespace SuperStarTrek.Objects
{ {
internal class Starbase internal class Starbase
{ {
private readonly Input _input;
private readonly Output _output;
private readonly double _repairDelay;
public Starbase(Random random, Input input)
{
_repairDelay = random.GetDouble() * 0.5;
_input = input;
}
public override string ToString() => ">!<"; public override string ToString() => ">!<";
internal bool TryRepair(Enterprise enterprise, out double repairTime)
{
repairTime = enterprise.DamagedSystemCount * 0.1 + _repairDelay;
if (repairTime >= 1) { repairTime = 0.9; }
_output.Write(Strings.RepairEstimate, repairTime);
if (_input.GetYesNo(Strings.RepairPrompt, Input.YesNoMode.TrueOnY))
{
foreach (var system in enterprise.Systems)
{
system.Repair();
}
return true;
}
repairTime = 0;
return false;
}
} }
} }

View File

@@ -4,12 +4,37 @@ namespace SuperStarTrek
{ {
internal class Output internal class Output
{ {
public void Write(string text) => Console.Write(text); public Output Write(string text)
public void Write(string format, params object[] args) => Console.Write(format, args); {
public void WriteLine(string text = "") => Console.WriteLine(text); Console.Write(text);
return this;
}
public void NextLine() => Console.WriteLine(); public Output Write(string format, params object[] args)
{
Console.Write(format, args);
return this;
}
public Output WriteLine(string text = "")
{
Console.WriteLine(text);
return this;
}
public Output NextLine()
{
Console.WriteLine();
return this;
}
public Output Prompt(string text = "")
{
Console.Write($"{text}? ");
return this;
}
public void Prompt(string text = "") => Console.Write($"{text}? ");
} }
} }

View File

@@ -0,0 +1,4 @@
Congratulations, Captain! The last Klingon battle cruiser
menacing the Federation has been destroyed.
Your efficiency rating is {0}.

View File

@@ -0,0 +1 @@
The Enterprise has been destroyed. The Federation will be conquered.

View File

@@ -0,0 +1,3 @@
Is is stardate {0}.
There were {1} Klingon battle cruisers left at
the end of your mission.

View File

@@ -1,3 +1,4 @@
INSTRUCTIONS FOR 'SUPER STAR TREK' INSTRUCTIONS FOR 'SUPER STAR TREK'
1. When you see "Command ?" printed, enter one of the legal 1. When you see "Command ?" printed, enter one of the legal

View File

@@ -0,0 +1,2 @@
Technicians standing by to effect repairs to your ship;
Estimated time to repair: {0} stardates.

View File

@@ -0,0 +1 @@
Will you authorize the repair order (Y/N)

View File

@@ -1,3 +1,5 @@
The Federation is in need of a new starship commander The Federation is in need of a new starship commander
for a similar mission -- if there is a volunteer for a similar mission -- if there is a volunteer
let him step forward and enter 'Aye' let him step forward and enter 'Aye'

View File

@@ -0,0 +1,3 @@
** FATAL ERROR ** You've just stranded your ship in space
You have insufficient maneuvering energy, and shield control
is presently incapable of cross-circuiting to engine room!!

View File

@@ -7,14 +7,20 @@ namespace SuperStarTrek.Resources
internal static class Strings internal static class Strings
{ {
public static string CombatArea => GetResource(); public static string CombatArea => GetResource();
public static string Congratulations => GetResource();
public static string Destroyed => 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 RepairEstimate => GetResource();
public static string RepairPrompt => GetResource();
public static string ReplayPrompt => GetResource(); public static string ReplayPrompt => GetResource();
public static string ShieldsDropped => GetResource(); public static string ShieldsDropped => GetResource();
public static string ShortRangeSensorsOut => GetResource(); public static string ShortRangeSensorsOut => GetResource();
public static string StartText => GetResource(); public static string StartText => GetResource();
public static string Stranded => GetResource();
public static string Title => GetResource(); public static string Title => GetResource();
private static string GetResource([CallerMemberName] string name = "") private static string GetResource([CallerMemberName] string name = "")

View File

@@ -23,7 +23,7 @@ namespace SuperStarTrek.Space
PositionObject(() => new Klingon(), _info.KlingonCount); PositionObject(() => new Klingon(), _info.KlingonCount);
if (_info.HasStarbase) if (_info.HasStarbase)
{ {
_starbaseSector = PositionObject(() => new Starbase()); _starbaseSector = PositionObject(() => new Starbase(_random, new Input(new Output())));
} }
PositionObject(() => new Star(), _info.StarCount); PositionObject(() => new Star(), _info.StarCount);
} }
@@ -31,6 +31,7 @@ namespace SuperStarTrek.Space
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 bool EnterpriseIsNextToStarbase => public bool EnterpriseIsNextToStarbase =>
_info.HasStarbase && _info.HasStarbase &&
Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 && Math.Abs(_enterpriseSector.X - _starbaseSector.X) <= 1 &&

View File

@@ -0,0 +1,49 @@
using SuperStarTrek.Objects;
using SuperStarTrek.Space;
namespace SuperStarTrek.Systems
{
internal class DamageControl : Subsystem
{
private readonly Enterprise _enterprise;
private readonly Output _output;
public DamageControl(Enterprise enterprise, Output output)
: base("Damage Control", Command.DAM)
{
_enterprise = enterprise;
_output = output;
}
public override void ExecuteCommand(Quadrant quadrant)
{
if (IsDamaged)
{
_output.WriteLine("Damage Control report not available");
}
else
{
WriteDamageReport();
}
if (_enterprise.DamagedSystemCount > 0 && _enterprise.IsDocked)
{
if (quadrant.Starbase.TryRepair(_enterprise, out var repairTime))
{
WriteDamageReport();
}
}
}
public void WriteDamageReport()
{
_output.NextLine().NextLine().WriteLine("Device State of Repair");
foreach (var system in _enterprise.Systems)
{
_output.Write(system.Name.PadRight(25))
.WriteLine(((int)(system.Condition * 100) * 0.01).ToString(" 0.##;-0.##"));
}
_output.NextLine();
}
}
}

View File

@@ -51,8 +51,8 @@ namespace SuperStarTrek.Systems
yield return $"Quadrant {_enterprise.Quadrant}"; yield return $"Quadrant {_enterprise.Quadrant}";
yield return $"Sector {_enterprise.Sector}"; yield return $"Sector {_enterprise.Sector}";
yield return $"Photon torpedoes {_enterprise.TorpedoCount}"; yield return $"Photon torpedoes {_enterprise.TorpedoCount}";
yield return $"Total energy {Math.Ceiling(_enterprise.Energy)}"; yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}";
yield return $"Shields {(int)_enterprise.Shields}"; yield return $"Shields {(int)_enterprise.Shields.Energy}";
yield return $"Klingons remaining {_galaxy.KlingonCount}"; yield return $"Klingons remaining {_galaxy.KlingonCount}";
} }
} }

View File

@@ -12,9 +12,14 @@ namespace SuperStarTrek.Systems
} }
public string Name { get; } public string Name { get; }
public double Condition { get; } public double Condition { get; private set; }
public bool IsDamaged => Condition < 0;
public Command Command { get; } public Command Command { get; }
public abstract void ExecuteCommand(Quadrant quadrant); public abstract void ExecuteCommand(Quadrant quadrant);
public void Repair()
{
if (Condition < 0) { Condition = 0; }
}
} }
} }