diff --git a/84 Super Star Trek/csharp/Game.cs b/84 Super Star Trek/csharp/Game.cs index d97b8198..eb9fe03c 100644 --- a/84 Super Star Trek/csharp/Game.cs +++ b/84 Super Star Trek/csharp/Game.cs @@ -33,11 +33,7 @@ namespace SuperStarTrek { _output.Write(Strings.Title); - _output.Write("Do you need instructions (Y/N)? "); - var response = Console.ReadLine(); - _output.WriteLine(); - - if (!response.Equals("N", InvariantCultureIgnoreCase)) + if (_input.GetYesNo("Do you need instructions", Input.YesNoMode.FalseOnN)) { _output.Write(Strings.Instructions); @@ -68,7 +64,16 @@ namespace SuperStarTrek { 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; _enterprise = new Enterprise(3000, random.GetCoordinate()); - _enterprise.Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) - .Add(new ShieldControl(_enterprise, _output, _input)); + _enterprise + .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output)) + .Add(new ShieldControl(_enterprise, _output, _input)) + .Add(new DamageControl(_enterprise, _output)); return new Quadrant(_galaxy[_currentQuadrant], _enterprise); } 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); } } diff --git a/84 Super Star Trek/csharp/Input.cs b/84 Super Star Trek/csharp/Input.cs index 98e5b297..3e2d7972 100644 --- a/84 Super Star Trek/csharp/Input.cs +++ b/84 Super Star Trek/csharp/Input.cs @@ -72,5 +72,26 @@ namespace SuperStarTrek _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 + } } } diff --git a/84 Super Star Trek/csharp/Objects/Enterprise.cs b/84 Super Star Trek/csharp/Objects/Enterprise.cs index 4f6055cc..e8447fca 100644 --- a/84 Super Star Trek/csharp/Objects/Enterprise.cs +++ b/84 Super Star Trek/csharp/Objects/Enterprise.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using SuperStarTrek.Resources; using SuperStarTrek.Space; @@ -13,7 +14,6 @@ namespace SuperStarTrek.Objects private readonly List _systems; private readonly Dictionary _commandExecutors; private Quadrant _quadrant; - private ShieldControl _shieldControl; public Enterprise(int maxEnergy, Coordinates sector) { @@ -27,11 +27,12 @@ namespace SuperStarTrek.Objects public Coordinates Quadrant => _quadrant.Coordinates; public Coordinates Sector { get; } public string Condition => GetCondition(); - public double Shields => _shieldControl.Energy; - public double Energy => TotalEnergy - Shields; + public ShieldControl Shields => (ShieldControl)_commandExecutors[Command.SHE]; + public double Energy => TotalEnergy - Shields.Energy; public double TotalEnergy { get; private set; } + public int DamagedSystemCount => _systems.Count(s => s.IsDamaged); + public IEnumerable Systems => _systems; public int TorpedoCount { get; } - public bool IsDocked { get; private set; } public Enterprise Add(Subsystem system) @@ -39,23 +40,9 @@ namespace SuperStarTrek.Objects _systems.Add(system); _commandExecutors[system.Command] = system; - if (system is ShieldControl shieldControl) { _shieldControl = shieldControl; } - 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) { _quadrant = quadrant; @@ -66,7 +53,7 @@ namespace SuperStarTrek.Objects if (quadrant.HasKlingons) { _output.Write(Strings.CombatArea); - if (Shields <= 200) { _output.Write(Strings.LowShields); } + if (Shields.Energy <= 200) { _output.Write(Strings.LowShields); } } IsDocked = quadrant.EnterpriseIsNextToStarbase; diff --git a/84 Super Star Trek/csharp/Objects/Starbase.cs b/84 Super Star Trek/csharp/Objects/Starbase.cs index 33110837..e11ca9f5 100644 --- a/84 Super Star Trek/csharp/Objects/Starbase.cs +++ b/84 Super Star Trek/csharp/Objects/Starbase.cs @@ -1,7 +1,38 @@ +using SuperStarTrek.Resources; + namespace SuperStarTrek.Objects { 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() => ">!<"; + + 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; + } } } diff --git a/84 Super Star Trek/csharp/Output.cs b/84 Super Star Trek/csharp/Output.cs index 77e5e919..ed960eea 100644 --- a/84 Super Star Trek/csharp/Output.cs +++ b/84 Super Star Trek/csharp/Output.cs @@ -4,12 +4,37 @@ namespace SuperStarTrek { internal class Output { - public void Write(string text) => Console.Write(text); - public void Write(string format, params object[] args) => Console.Write(format, args); - public void WriteLine(string text = "") => Console.WriteLine(text); + public Output Write(string 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}? "); } } diff --git a/84 Super Star Trek/csharp/Resources/AcceptCommand.txt b/84 Super Star Trek/csharp/Resources/AcceptCommand.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/84 Super Star Trek/csharp/Resources/Congratulations.txt b/84 Super Star Trek/csharp/Resources/Congratulations.txt new file mode 100644 index 00000000..767f8653 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Congratulations.txt @@ -0,0 +1,4 @@ +Congratulations, Captain! The last Klingon battle cruiser +menacing the Federation has been destroyed. + +Your efficiency rating is {0}. diff --git a/84 Super Star Trek/csharp/Resources/Destroyed.txt b/84 Super Star Trek/csharp/Resources/Destroyed.txt new file mode 100644 index 00000000..881d7b49 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Destroyed.txt @@ -0,0 +1 @@ +The Enterprise has been destroyed. The Federation will be conquered. diff --git a/84 Super Star Trek/csharp/Resources/EndOfMission.txt b/84 Super Star Trek/csharp/Resources/EndOfMission.txt new file mode 100644 index 00000000..f6995e31 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/EndOfMission.txt @@ -0,0 +1,3 @@ +Is is stardate {0}. +There were {1} Klingon battle cruisers left at +the end of your mission. diff --git a/84 Super Star Trek/csharp/Resources/Instructions.txt b/84 Super Star Trek/csharp/Resources/Instructions.txt index fd74857e..34b4169c 100644 --- a/84 Super Star Trek/csharp/Resources/Instructions.txt +++ b/84 Super Star Trek/csharp/Resources/Instructions.txt @@ -1,3 +1,4 @@ + INSTRUCTIONS FOR 'SUPER STAR TREK' 1. When you see "Command ?" printed, enter one of the legal diff --git a/84 Super Star Trek/csharp/Resources/RepairEstimate.txt b/84 Super Star Trek/csharp/Resources/RepairEstimate.txt new file mode 100644 index 00000000..12e167a5 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/RepairEstimate.txt @@ -0,0 +1,2 @@ +Technicians standing by to effect repairs to your ship; +Estimated time to repair: {0} stardates. diff --git a/84 Super Star Trek/csharp/Resources/RepairPrompt.txt b/84 Super Star Trek/csharp/Resources/RepairPrompt.txt new file mode 100644 index 00000000..feffdb27 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/RepairPrompt.txt @@ -0,0 +1 @@ +Will you authorize the repair order (Y/N) \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt b/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt index 52aca0d1..3ca3a102 100644 --- a/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt +++ b/84 Super Star Trek/csharp/Resources/ReplayPrompt.txt @@ -1,3 +1,5 @@ + + The Federation is in need of a new starship commander for a similar mission -- if there is a volunteer let him step forward and enter 'Aye' \ No newline at end of file diff --git a/84 Super Star Trek/csharp/Resources/Stranded.txt b/84 Super Star Trek/csharp/Resources/Stranded.txt new file mode 100644 index 00000000..07c37952 --- /dev/null +++ b/84 Super Star Trek/csharp/Resources/Stranded.txt @@ -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!! diff --git a/84 Super Star Trek/csharp/Resources/Strings.cs b/84 Super Star Trek/csharp/Resources/Strings.cs index 930f1663..4592db31 100644 --- a/84 Super Star Trek/csharp/Resources/Strings.cs +++ b/84 Super Star Trek/csharp/Resources/Strings.cs @@ -7,14 +7,20 @@ namespace SuperStarTrek.Resources internal static class Strings { 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 Instructions => GetResource(); public static string LowShields => GetResource(); public static string Orders => GetResource(); + public static string RepairEstimate => GetResource(); + public static string RepairPrompt => GetResource(); public static string ReplayPrompt => GetResource(); public static string ShieldsDropped => GetResource(); public static string ShortRangeSensorsOut => GetResource(); public static string StartText => GetResource(); + public static string Stranded => GetResource(); public static string Title => GetResource(); private static string GetResource([CallerMemberName] string name = "") diff --git a/84 Super Star Trek/csharp/Space/Quadrant.cs b/84 Super Star Trek/csharp/Space/Quadrant.cs index 2aa45b6d..f08fa18b 100644 --- a/84 Super Star Trek/csharp/Space/Quadrant.cs +++ b/84 Super Star Trek/csharp/Space/Quadrant.cs @@ -23,7 +23,7 @@ namespace SuperStarTrek.Space PositionObject(() => new Klingon(), _info.KlingonCount); if (_info.HasStarbase) { - _starbaseSector = PositionObject(() => new Starbase()); + _starbaseSector = PositionObject(() => new Starbase(_random, new Input(new Output()))); } PositionObject(() => new Star(), _info.StarCount); } @@ -31,6 +31,7 @@ namespace SuperStarTrek.Space 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 && diff --git a/84 Super Star Trek/csharp/Systems/DamageControl.cs b/84 Super Star Trek/csharp/Systems/DamageControl.cs new file mode 100644 index 00000000..5cfbda7e --- /dev/null +++ b/84 Super Star Trek/csharp/Systems/DamageControl.cs @@ -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(); + } + } +} diff --git a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs index d22dda70..6632705c 100644 --- a/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs +++ b/84 Super Star Trek/csharp/Systems/ShortRangeSensors.cs @@ -51,8 +51,8 @@ namespace SuperStarTrek.Systems yield return $"Quadrant {_enterprise.Quadrant}"; yield return $"Sector {_enterprise.Sector}"; yield return $"Photon torpedoes {_enterprise.TorpedoCount}"; - yield return $"Total energy {Math.Ceiling(_enterprise.Energy)}"; - yield return $"Shields {(int)_enterprise.Shields}"; + yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}"; + yield return $"Shields {(int)_enterprise.Shields.Energy}"; yield return $"Klingons remaining {_galaxy.KlingonCount}"; } } diff --git a/84 Super Star Trek/csharp/Systems/Subsystem.cs b/84 Super Star Trek/csharp/Systems/Subsystem.cs index ae2ef7d6..9cb461ce 100644 --- a/84 Super Star Trek/csharp/Systems/Subsystem.cs +++ b/84 Super Star Trek/csharp/Systems/Subsystem.cs @@ -12,9 +12,14 @@ namespace SuperStarTrek.Systems } public string Name { get; } - public double Condition { get; } + public double Condition { get; private set; } + public bool IsDamaged => Condition < 0; public Command Command { get; } public abstract void ExecuteCommand(Quadrant quadrant); + public void Repair() + { + if (Condition < 0) { Condition = 0; } + } } }