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("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);
}
}

View File

@@ -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
}
}
}

View File

@@ -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<Subsystem> _systems;
private readonly Dictionary<Command, Subsystem> _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<Subsystem> 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;

View File

@@ -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;
}
}
}

View File

@@ -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}? ");
}
}

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'
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
for a similar mission -- if there is a volunteer
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
{
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 = "")

View File

@@ -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 &&

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 $"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}";
}
}

View File

@@ -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; }
}
}
}