diff --git a/00_Common/dotnet/Games.Common/IO/ConsoleIO.cs b/00_Common/dotnet/Games.Common/IO/ConsoleIO.cs
index a24238bf..a1f77083 100644
--- a/00_Common/dotnet/Games.Common/IO/ConsoleIO.cs
+++ b/00_Common/dotnet/Games.Common/IO/ConsoleIO.cs
@@ -12,4 +12,6 @@ public sealed class ConsoleIO : TextIO
: base(Console.In, Console.Out)
{
}
+
+ public override char ReadCharacter() => Console.ReadKey(intercept: true).KeyChar;
}
diff --git a/00_Common/dotnet/Games.Common/IO/IReadWrite.cs b/00_Common/dotnet/Games.Common/IO/IReadWrite.cs
index 02ab573e..3d2cfc7e 100644
--- a/00_Common/dotnet/Games.Common/IO/IReadWrite.cs
+++ b/00_Common/dotnet/Games.Common/IO/IReadWrite.cs
@@ -8,6 +8,12 @@ namespace Games.Common.IO;
///
public interface IReadWrite
{
+ ///
+ /// Reads a character from input.
+ ///
+ /// The character read.
+ char ReadCharacter();
+
///
/// Reads a value from input.
///
@@ -99,6 +105,13 @@ public interface IReadWrite
///
/// The format to be written.
/// The values to be inserted into the format.
+ void Write(string format, params object[] values);
+
+ ///
+ /// Writes a formatted string to output followed by a new-line.
+ ///
+ /// The format to be written.
+ /// The values to be inserted into the format.
void WriteLine(string format, params object[] values);
///
diff --git a/00_Common/dotnet/Games.Common/IO/TextIO.cs b/00_Common/dotnet/Games.Common/IO/TextIO.cs
index c2584e69..5a31e37c 100644
--- a/00_Common/dotnet/Games.Common/IO/TextIO.cs
+++ b/00_Common/dotnet/Games.Common/IO/TextIO.cs
@@ -29,6 +29,15 @@ public class TextIO : IReadWrite
_numberTokenReader = TokenReader.ForNumbers(this);
}
+ public virtual char ReadCharacter()
+ {
+ while(true)
+ {
+ var ch = _input.Read();
+ if (ch != -1) { return (char)ch; }
+ }
+ }
+
public float ReadNumber(string prompt) => ReadNumbers(prompt, 1)[0];
public (float, float) Read2Numbers(string prompt)
@@ -99,6 +108,8 @@ public class TextIO : IReadWrite
public void WriteLine(object value) => _output.WriteLine(value.ToString());
+ public void Write(string format, params object[] values) => _output.Write(format, values);
+
public void WriteLine(string format, params object[] values) => _output.WriteLine(format, values);
public void Write(Stream stream, bool keepOpen = false)
diff --git a/84_Super_Star_Trek/csharp/Commands/Command.cs b/84_Super_Star_Trek/csharp/Commands/Command.cs
index f0d569f8..e6b65db9 100644
--- a/84_Super_Star_Trek/csharp/Commands/Command.cs
+++ b/84_Super_Star_Trek/csharp/Commands/Command.cs
@@ -1,34 +1,33 @@
using System.ComponentModel;
-namespace SuperStarTrek.Commands
+namespace SuperStarTrek.Commands;
+
+internal enum Command
{
- internal enum Command
- {
- [Description("To set course")]
- NAV,
+ [Description("To set course")]
+ NAV,
- [Description("For short range sensor scan")]
- SRS,
+ [Description("For short range sensor scan")]
+ SRS,
- [Description("For long range sensor scan")]
- LRS,
+ [Description("For long range sensor scan")]
+ LRS,
- [Description("To fire phasers")]
- PHA,
+ [Description("To fire phasers")]
+ PHA,
- [Description("To fire photon torpedoes")]
- TOR,
+ [Description("To fire photon torpedoes")]
+ TOR,
- [Description("To raise or lower shields")]
- SHE,
+ [Description("To raise or lower shields")]
+ SHE,
- [Description("For damage control reports")]
- DAM,
+ [Description("For damage control reports")]
+ DAM,
- [Description("To call on library-computer")]
- COM,
+ [Description("To call on library-computer")]
+ COM,
- [Description("To resign your command")]
- XXX
- }
+ [Description("To resign your command")]
+ XXX
}
diff --git a/84_Super_Star_Trek/csharp/Commands/CommandExtensions.cs b/84_Super_Star_Trek/csharp/Commands/CommandExtensions.cs
index f8f7e9da..e3e2f7aa 100644
--- a/84_Super_Star_Trek/csharp/Commands/CommandExtensions.cs
+++ b/84_Super_Star_Trek/csharp/Commands/CommandExtensions.cs
@@ -1,14 +1,13 @@
using System.Reflection;
using System.ComponentModel;
-namespace SuperStarTrek.Commands
+namespace SuperStarTrek.Commands;
+
+internal static class CommandExtensions
{
- internal static class CommandExtensions
- {
- internal static string GetDescription(this Command command) =>
- typeof(Command)
- .GetField(command.ToString())
- .GetCustomAttribute()
- .Description;
- }
+ internal static string GetDescription(this Command command) =>
+ typeof(Command)
+ .GetField(command.ToString())
+ .GetCustomAttribute()
+ .Description;
}
diff --git a/84_Super_Star_Trek/csharp/Commands/CommandResult.cs b/84_Super_Star_Trek/csharp/Commands/CommandResult.cs
index 1b02780c..be95526f 100644
--- a/84_Super_Star_Trek/csharp/Commands/CommandResult.cs
+++ b/84_Super_Star_Trek/csharp/Commands/CommandResult.cs
@@ -1,23 +1,22 @@
-namespace SuperStarTrek.Commands
+namespace SuperStarTrek.Commands;
+
+internal class CommandResult
{
- internal class CommandResult
+ public static readonly CommandResult Ok = new(false);
+ public static readonly CommandResult GameOver = new(true);
+
+ private CommandResult(bool isGameOver)
{
- public static readonly CommandResult Ok = new(false);
- public static readonly CommandResult GameOver = new(true);
-
- private CommandResult(bool isGameOver)
- {
- IsGameOver = isGameOver;
- }
-
- private CommandResult(float timeElapsed)
- {
- TimeElapsed = timeElapsed;
- }
-
- public bool IsGameOver { get; }
- public float TimeElapsed { get; }
-
- public static CommandResult Elapsed(float timeElapsed) => new(timeElapsed);
+ IsGameOver = isGameOver;
}
+
+ private CommandResult(float timeElapsed)
+ {
+ TimeElapsed = timeElapsed;
+ }
+
+ public bool IsGameOver { get; }
+ public float TimeElapsed { get; }
+
+ public static CommandResult Elapsed(float timeElapsed) => new(timeElapsed);
}
diff --git a/84_Super_Star_Trek/csharp/Game.cs b/84_Super_Star_Trek/csharp/Game.cs
index 274e2948..918b9f65 100644
--- a/84_Super_Star_Trek/csharp/Game.cs
+++ b/84_Super_Star_Trek/csharp/Game.cs
@@ -1,131 +1,128 @@
using System;
+using Games.Common.IO;
+using Games.Common.Randomness;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
using SuperStarTrek.Systems;
using SuperStarTrek.Systems.ComputerFunctions;
-namespace SuperStarTrek
+namespace SuperStarTrek;
+
+internal class Game
{
- internal class Game
+ private readonly TextIO _io;
+ private readonly IRandom _random;
+
+ private int _initialStardate;
+ private int _finalStarDate;
+ private float _currentStardate;
+ private Coordinates _currentQuadrant;
+ private Galaxy _galaxy;
+ private int _initialKlingonCount;
+ private Enterprise _enterprise;
+
+ internal Game(TextIO io, IRandom random)
{
- private readonly Output _output;
- private readonly Input _input;
- private readonly Random _random;
-
- private int _initialStardate;
- private int _finalStarDate;
- private float _currentStardate;
- private Coordinates _currentQuadrant;
- private Galaxy _galaxy;
- private int _initialKlingonCount;
- private Enterprise _enterprise;
-
- internal Game(Output output, Input input, Random random)
- {
- _output = output;
- _input = input;
- _random = random;
- }
-
- internal float Stardate => _currentStardate;
-
- internal float StardatesRemaining => _finalStarDate - _currentStardate;
-
- internal void DoIntroduction()
- {
- _output.Write(Strings.Title);
-
- if (_input.GetYesNo("Do you need instructions", Input.YesNoMode.FalseOnN))
- {
- _output.Write(Strings.Instructions);
-
- _input.WaitForAnyKeyButEnter("to continue");
- }
- }
-
- internal void Play()
- {
- Initialise();
- var gameOver = false;
-
- while (!gameOver)
- {
- var command = _input.GetCommand();
-
- var result = _enterprise.Execute(command);
-
- gameOver = result.IsGameOver || CheckIfStranded();
- _currentStardate += result.TimeElapsed;
- gameOver |= _currentStardate > _finalStarDate;
- }
-
- if (_galaxy.KlingonCount > 0)
- {
- _output.Write(Strings.EndOfMission, _currentStardate, _galaxy.KlingonCount);
- }
- else
- {
- _output.Write(Strings.Congratulations, GetEfficiency());
- }
- }
-
- private void Initialise()
- {
- _currentStardate = _initialStardate = _random.GetInt(20, 40) * 100;
- _finalStarDate = _initialStardate + _random.GetInt(25, 35);
-
- _currentQuadrant = _random.GetCoordinate();
-
- _galaxy = new Galaxy(_random);
- _initialKlingonCount = _galaxy.KlingonCount;
-
- _enterprise = new Enterprise(3000, _random.GetCoordinate(), _output, _random, _input);
- _enterprise
- .Add(new WarpEngines(_enterprise, _output, _input))
- .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _output))
- .Add(new LongRangeSensors(_galaxy, _output))
- .Add(new PhaserControl(_enterprise, _output, _input, _random))
- .Add(new PhotonTubes(10, _enterprise, _output, _input))
- .Add(new ShieldControl(_enterprise, _output, _input))
- .Add(new DamageControl(_enterprise, _output))
- .Add(new LibraryComputer(
- _output,
- _input,
- new CumulativeGalacticRecord(_output, _galaxy),
- new StatusReport(this, _galaxy, _enterprise, _output),
- new TorpedoDataCalculator(_enterprise, _output),
- new StarbaseDataCalculator(_enterprise, _output),
- new DirectionDistanceCalculator(_enterprise, _output, _input),
- new GalaxyRegionMap(_output, _galaxy)));
-
- _output.Write(Strings.Enterprise);
- _output.Write(
- Strings.Orders,
- _galaxy.KlingonCount,
- _finalStarDate,
- _finalStarDate - _initialStardate,
- _galaxy.StarbaseCount > 1 ? "are" : "is",
- _galaxy.StarbaseCount,
- _galaxy.StarbaseCount > 1 ? "s" : "");
-
- _input.WaitForAnyKeyButEnter("when ready to accept command");
-
- _enterprise.StartIn(BuildCurrentQuadrant());
- }
-
- private Quadrant BuildCurrentQuadrant() =>
- new Quadrant(_galaxy[_currentQuadrant], _enterprise, _random, _galaxy, _input, _output);
-
- internal bool Replay() => _galaxy.StarbaseCount > 0 && _input.GetString(Strings.ReplayPrompt, "Aye");
-
- private bool CheckIfStranded()
- {
- if (_enterprise.IsStranded) { _output.Write(Strings.Stranded); }
- return _enterprise.IsStranded;
- }
-
- private float GetEfficiency() =>
- 1000 * (float)Math.Pow(_initialKlingonCount / (_currentStardate - _initialStardate), 2);
+ _io = io;
+ _random = random;
}
+
+ internal float Stardate => _currentStardate;
+
+ internal float StardatesRemaining => _finalStarDate - _currentStardate;
+
+ internal void DoIntroduction()
+ {
+ _io.Write(Strings.Title);
+
+ if (_io.GetYesNo("Do you need instructions", IReadWriteExtensions.YesNoMode.FalseOnN))
+ {
+ _io.Write(Strings.Instructions);
+
+ _io.WaitForAnyKeyButEnter("to continue");
+ }
+ }
+
+ internal void Play()
+ {
+ Initialise();
+ var gameOver = false;
+
+ while (!gameOver)
+ {
+ var command = _io.ReadCommand();
+
+ var result = _enterprise.Execute(command);
+
+ gameOver = result.IsGameOver || CheckIfStranded();
+ _currentStardate += result.TimeElapsed;
+ gameOver |= _currentStardate > _finalStarDate;
+ }
+
+ if (_galaxy.KlingonCount > 0)
+ {
+ _io.Write(Strings.EndOfMission, _currentStardate, _galaxy.KlingonCount);
+ }
+ else
+ {
+ _io.Write(Strings.Congratulations, CalculateEfficiency());
+ }
+ }
+
+ private void Initialise()
+ {
+ _currentStardate = _initialStardate = _random.Next(20, 40) * 100;
+ _finalStarDate = _initialStardate + _random.Next(25, 35);
+
+ _currentQuadrant = _random.NextCoordinate();
+
+ _galaxy = new Galaxy(_random);
+ _initialKlingonCount = _galaxy.KlingonCount;
+
+ _enterprise = new Enterprise(3000, _random.NextCoordinate(), _io, _random);
+ _enterprise
+ .Add(new WarpEngines(_enterprise, _io))
+ .Add(new ShortRangeSensors(_enterprise, _galaxy, this, _io))
+ .Add(new LongRangeSensors(_galaxy, _io))
+ .Add(new PhaserControl(_enterprise, _io, _random))
+ .Add(new PhotonTubes(10, _enterprise, _io))
+ .Add(new ShieldControl(_enterprise, _io))
+ .Add(new DamageControl(_enterprise, _io))
+ .Add(new LibraryComputer(
+ _io,
+ new CumulativeGalacticRecord(_io, _galaxy),
+ new StatusReport(this, _galaxy, _enterprise, _io),
+ new TorpedoDataCalculator(_enterprise, _io),
+ new StarbaseDataCalculator(_enterprise, _io),
+ new DirectionDistanceCalculator(_enterprise, _io),
+ new GalaxyRegionMap(_io, _galaxy)));
+
+ _io.Write(Strings.Enterprise);
+ _io.Write(
+ Strings.Orders,
+ _galaxy.KlingonCount,
+ _finalStarDate,
+ _finalStarDate - _initialStardate,
+ _galaxy.StarbaseCount > 1 ? "are" : "is",
+ _galaxy.StarbaseCount,
+ _galaxy.StarbaseCount > 1 ? "s" : "");
+
+ _io.WaitForAnyKeyButEnter("when ready to accept command");
+
+ _enterprise.StartIn(BuildCurrentQuadrant());
+ }
+
+ private Quadrant BuildCurrentQuadrant() => new(_galaxy[_currentQuadrant], _enterprise, _random, _galaxy, _io);
+
+ internal bool Replay() => _galaxy.StarbaseCount > 0 && _io.ReadExpectedString(Strings.ReplayPrompt, "Aye");
+
+ private bool CheckIfStranded()
+ {
+ if (_enterprise.IsStranded) { _io.Write(Strings.Stranded); }
+ return _enterprise.IsStranded;
+ }
+
+ private float CalculateEfficiency() =>
+ 1000 * (float)Math.Pow(_initialKlingonCount / (_currentStardate - _initialStardate), 2);
}
diff --git a/84_Super_Star_Trek/csharp/IRandomExtensions.cs b/84_Super_Star_Trek/csharp/IRandomExtensions.cs
new file mode 100644
index 00000000..f115aeed
--- /dev/null
+++ b/84_Super_Star_Trek/csharp/IRandomExtensions.cs
@@ -0,0 +1,16 @@
+using Games.Common.Randomness;
+using SuperStarTrek.Space;
+
+namespace SuperStarTrek;
+
+internal static class IRandomExtensions
+{
+ internal static Coordinates NextCoordinate(this IRandom random) =>
+ new Coordinates(random.Next1To8Inclusive() - 1, random.Next1To8Inclusive() - 1);
+
+ // Duplicates the algorithm used in the original code to get an integer value from 1 to 8, inclusive:
+ // 475 DEF FNR(R)=INT(RND(R)*7.98+1.01)
+ // Returns a value from 1 to 8, inclusive.
+ // Note there's a slight bias away from the extreme values, 1 and 8.
+ internal static int Next1To8Inclusive(this IRandom random) => (int)(random.NextFloat() * 7.98 + 1.01);
+}
diff --git a/84_Super_Star_Trek/csharp/IReadWriteExtensions.cs b/84_Super_Star_Trek/csharp/IReadWriteExtensions.cs
new file mode 100644
index 00000000..f46e74f7
--- /dev/null
+++ b/84_Super_Star_Trek/csharp/IReadWriteExtensions.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Linq;
+using Games.Common.IO;
+using SuperStarTrek.Commands;
+using SuperStarTrek.Space;
+using static System.StringComparison;
+
+namespace SuperStarTrek;
+
+internal static class IReadWriteExtensions
+{
+ internal static void WaitForAnyKeyButEnter(this IReadWrite io, string prompt)
+ {
+ io.Write($"Hit any key but Enter {prompt} ");
+ while (io.ReadCharacter() == '\r');
+ }
+
+ internal static (float X, float Y) GetCoordinates(this IReadWrite io, string prompt) =>
+ io.Read2Numbers($"{prompt} (X,Y)");
+
+ internal static bool TryReadNumberInRange(
+ this IReadWrite io,
+ string prompt,
+ float minValue,
+ float maxValue,
+ out float value)
+ {
+ value = io.ReadNumber($"{prompt} ({minValue}-{maxValue})");
+
+ return value >= minValue && value <= maxValue;
+ }
+
+ internal static bool ReadExpectedString(this IReadWrite io, string prompt, string trueValue) =>
+ io.ReadString(prompt).Equals(trueValue, InvariantCultureIgnoreCase);
+
+ internal static Command ReadCommand(this IReadWrite io)
+ {
+ while(true)
+ {
+ var response = io.ReadString("Command");
+
+ if (response.Length >= 3 &&
+ Enum.TryParse(response.Substring(0, 3), ignoreCase: true, out Command parsedCommand))
+ {
+ return parsedCommand;
+ }
+
+ io.WriteLine("Enter one of the following:");
+ foreach (var command in Enum.GetValues(typeof(Command)).OfType())
+ {
+ io.WriteLine($" {command} ({command.GetDescription()})");
+ }
+ io.WriteLine();
+ }
+ }
+
+ internal static bool TryReadCourse(this IReadWrite io, string prompt, string officer, out Course course)
+ {
+ if (!io.TryReadNumberInRange(prompt, 1, 9, out var direction))
+ {
+ io.WriteLine($"{officer} reports, 'Incorrect course data, sir!'");
+ course = default;
+ return false;
+ }
+
+ course = new Course(direction);
+ return true;
+ }
+
+ internal static bool GetYesNo(this IReadWrite io, string prompt, YesNoMode mode)
+ {
+ var response = io.ReadString($"{prompt} (Y/N)").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")
+ };
+ }
+
+ internal enum YesNoMode
+ {
+ TrueOnY,
+ FalseOnN
+ }
+}
diff --git a/84_Super_Star_Trek/csharp/Input.cs b/84_Super_Star_Trek/csharp/Input.cs
deleted file mode 100644
index 2b37b2ba..00000000
--- a/84_Super_Star_Trek/csharp/Input.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-using System;
-using System.Linq;
-using SuperStarTrek.Commands;
-using SuperStarTrek.Space;
-using static System.StringComparison;
-
-namespace SuperStarTrek
-{
- internal class Input
- {
- private readonly Output _output;
-
- internal Input(Output output)
- {
- _output = output;
- }
-
- internal void WaitForAnyKeyButEnter(string prompt)
- {
- _output.Write($"Hit any key but Enter {prompt} ");
- while (Console.ReadKey(intercept: true).Key == ConsoleKey.Enter);
- }
-
- internal string GetString(string prompt)
- {
- _output.Prompt(prompt);
- return Console.ReadLine();
- }
-
- internal float GetNumber(string prompt)
- {
- _output.Prompt(prompt);
-
- while (true)
- {
- var response = Console.ReadLine();
- if (float.TryParse(response, out var value))
- {
- return value;
- }
-
- _output.WriteLine("!Number expected - retry input line");
- _output.Prompt();
- }
- }
-
- internal (float X, float Y) GetCoordinates(string prompt)
- {
- _output.Prompt($"{prompt} (X,Y)");
- var responses = ReadNumbers(2);
- return (responses[0], responses[1]);
- }
-
- internal bool TryGetNumber(string prompt, float minValue, float maxValue, out float value)
- {
- value = GetNumber($"{prompt} ({minValue}-{maxValue})");
-
- return value >= minValue && value <= maxValue;
- }
-
- internal bool GetString(string replayPrompt, string trueValue) =>
- GetString(replayPrompt).Equals(trueValue, InvariantCultureIgnoreCase);
-
- internal Command GetCommand()
- {
- while(true)
- {
- var response = GetString("Command");
-
- if (response.Length >= 3 &&
- Enum.TryParse(response.Substring(0, 3), ignoreCase: true, out Command parsedCommand))
- {
- return parsedCommand;
- }
-
- _output.WriteLine("Enter one of the following:");
- foreach (var command in Enum.GetValues(typeof(Command)).OfType())
- {
- _output.WriteLine($" {command} ({command.GetDescription()})");
- }
- _output.WriteLine();
- }
- }
-
- internal bool TryGetCourse(string prompt, string officer, out Course course)
- {
- if (!TryGetNumber(prompt, 1, 9, out var direction))
- {
- _output.WriteLine($"{officer} reports, 'Incorrect course data, sir!'");
- course = default;
- return false;
- }
-
- course = new Course(direction);
- return true;
- }
-
- internal 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")
- };
- }
-
- private float[] ReadNumbers(int quantity)
- {
- var numbers = new float[quantity];
- var index = 0;
- bool tryAgain;
-
- do
- {
- tryAgain = false;
- var responses = Console.ReadLine().Split(',');
- if (responses.Length > quantity)
- {
- _output.WriteLine("!Extra input ingored");
- }
-
- for (; index < responses.Length; index++)
- {
- if (!float.TryParse(responses[index], out numbers[index]))
- {
- _output.WriteLine("!Number expected - retry input line");
- _output.Prompt();
- tryAgain = true;
- break;
- }
- }
- } while (tryAgain);
-
- if (index < quantity)
- {
- _output.Prompt("?");
- var responses = ReadNumbers(quantity - index);
- for (int i = 0; i < responses.Length; i++, index++)
- {
- numbers[index] = responses[i];
- }
- }
-
- return numbers;
- }
-
- internal 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 ac9e8112..f288e920 100644
--- a/84_Super_Star_Trek/csharp/Objects/Enterprise.cs
+++ b/84_Super_Star_Trek/csharp/Objects/Enterprise.cs
@@ -1,231 +1,230 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Games.Common.IO;
+using Games.Common.Randomness;
using SuperStarTrek.Commands;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
using SuperStarTrek.Systems;
-namespace SuperStarTrek.Objects
+namespace SuperStarTrek.Objects;
+
+internal class Enterprise
{
- internal class Enterprise
+ private readonly int _maxEnergy;
+ private readonly IReadWrite _io;
+ private readonly List _systems;
+ private readonly Dictionary _commandExecutors;
+ private readonly IRandom _random;
+ private Quadrant _quadrant;
+
+ public Enterprise(int maxEnergy, Coordinates sector, IReadWrite io, IRandom random)
{
- private readonly int _maxEnergy;
- private readonly Output _output;
- private readonly List _systems;
- private readonly Dictionary _commandExecutors;
- private readonly Random _random;
- private readonly Input _input;
- private Quadrant _quadrant;
+ SectorCoordinates = sector;
+ TotalEnergy = _maxEnergy = maxEnergy;
- public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random, Input input)
- {
- SectorCoordinates = sector;
- TotalEnergy = _maxEnergy = maxEnergy;
-
- _systems = new List();
- _commandExecutors = new Dictionary();
- _output = output;
- _random = random;
- _input = input;
- }
-
- internal Quadrant Quadrant => _quadrant;
-
- internal Coordinates QuadrantCoordinates => _quadrant.Coordinates;
-
- internal Coordinates SectorCoordinates { get; private set; }
-
- internal string Condition => GetCondition();
-
- internal LibraryComputer Computer => (LibraryComputer)_commandExecutors[Command.COM];
-
- internal ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE];
-
- internal float Energy => TotalEnergy - ShieldControl.ShieldEnergy;
-
- internal float TotalEnergy { get; private set; }
-
- internal int DamagedSystemCount => _systems.Count(s => s.IsDamaged);
-
- internal IEnumerable Systems => _systems;
-
- internal PhotonTubes PhotonTubes => (PhotonTubes)_commandExecutors[Command.TOR];
-
- internal bool IsDocked => _quadrant.EnterpriseIsNextToStarbase;
-
- internal bool IsStranded => TotalEnergy < 10 || Energy < 10 && ShieldControl.IsDamaged;
-
- internal Enterprise Add(Subsystem system)
- {
- _systems.Add(system);
- _commandExecutors[system.Command] = system;
-
- return this;
- }
-
- internal void StartIn(Quadrant quadrant)
- {
- _quadrant = quadrant;
- quadrant.Display(Strings.StartText);
- }
-
- private string GetCondition() =>
- IsDocked switch
- {
- true => "Docked",
- false when _quadrant.HasKlingons => "*Red*",
- false when Energy / _maxEnergy < 0.1f => "Yellow",
- false => "Green"
- };
-
- internal CommandResult Execute(Command command)
- {
- if (command == Command.XXX) { return CommandResult.GameOver; }
-
- return _commandExecutors[command].ExecuteCommand(_quadrant);
- }
-
- internal void Refuel() => TotalEnergy = _maxEnergy;
-
- public override string ToString() => "<*>";
-
- internal void UseEnergy(float amountUsed)
- {
- TotalEnergy -= amountUsed;
- }
-
- 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($" ");
-
- if (hitStrength >= 20)
- {
- TakeDamage(hitStrength);
- }
-
- return CommandResult.Ok;
- }
-
- private void TakeDamage(float hitStrength)
- {
- var hitShieldRatio = hitStrength / ShieldControl.ShieldEnergy;
- if (_random.GetFloat() > 0.6 || hitShieldRatio <= 0.02f)
- {
- return;
- }
-
- var system = _systems[_random.Get1To8Inclusive() - 1];
- system.TakeDamage(hitShieldRatio + 0.5f * _random.GetFloat());
- _output.WriteLine($"Damage Control reports, '{system.Name} damaged by the hit.'");
- }
-
- internal void RepairSystems(float repairWorkDone)
- {
- var repairedSystems = new List();
-
- foreach (var system in _systems.Where(s => s.IsDamaged))
- {
- if (system.Repair(repairWorkDone))
- {
- repairedSystems.Add(system.Name);
- }
- }
-
- if (repairedSystems.Any())
- {
- _output.WriteLine("Damage Control report:");
- foreach (var systemName in repairedSystems)
- {
- _output.WriteLine($" {systemName} repair completed.");
- }
- }
- }
-
- internal void VaryConditionOfRandomSystem()
- {
- if (_random.GetFloat() > 0.2f) { return; }
-
- var system = _systems[_random.Get1To8Inclusive() - 1];
- _output.Write($"Damage Control report: {system.Name} ");
- if (_random.GetFloat() >= 0.6)
- {
- system.Repair(_random.GetFloat() * 3 + 1);
- _output.WriteLine("state of repair improved");
- }
- else
- {
- system.TakeDamage(_random.GetFloat() * 5 + 1);
- _output.WriteLine("damaged");
- }
- }
-
- internal float Move(Course course, float warpFactor, int distance)
- {
- var (quadrant, sector) = MoveWithinQuadrant(course, distance) ?? MoveBeyondQuadrant(course, distance);
-
- if (quadrant != _quadrant.Coordinates)
- {
- _quadrant = new Quadrant(_quadrant.Galaxy[quadrant], this, _random, _quadrant.Galaxy, _input, _output);
- }
- _quadrant.SetEnterpriseSector(sector);
- SectorCoordinates = sector;
-
- TotalEnergy -= distance + 10;
- if (Energy < 0)
- {
- _output.WriteLine("Shield Control supplies energy to complete the maneuver.");
- ShieldControl.ShieldEnergy = Math.Max(0, TotalEnergy);
- }
-
- return GetTimeElapsed(quadrant, warpFactor);
- }
-
- private (Coordinates, Coordinates)? MoveWithinQuadrant(Course course, int distance)
- {
- var currentSector = SectorCoordinates;
- foreach (var (sector, index) in course.GetSectorsFrom(SectorCoordinates).Select((s, i) => (s, i)))
- {
- if (distance == 0) { break; }
-
- if (_quadrant.HasObjectAt(sector))
- {
- _output.WriteLine($"Warp engines shut down at sector {currentSector} dues to bad navigation");
- distance = 0;
- break;
- }
-
- currentSector = sector;
- distance -= 1;
- }
-
- return distance == 0 ? (_quadrant.Coordinates, currentSector) : null;
- }
-
- private (Coordinates, Coordinates) MoveBeyondQuadrant(Course course, int distance)
- {
- var (complete, quadrant, sector) = course.GetDestination(QuadrantCoordinates, SectorCoordinates, distance);
-
- if (!complete)
- {
- _output.Write(Strings.PermissionDenied, sector, quadrant);
- }
-
- return (quadrant, sector);
- }
-
- private float GetTimeElapsed(Coordinates finalQuadrant, float warpFactor) =>
- finalQuadrant == _quadrant.Coordinates
- ? Math.Min(1, (float)Math.Round(warpFactor, 1, MidpointRounding.ToZero))
- : 1;
+ _systems = new List();
+ _commandExecutors = new Dictionary();
+ _io = io;
+ _random = random;
}
+
+ internal Quadrant Quadrant => _quadrant;
+
+ internal Coordinates QuadrantCoordinates => _quadrant.Coordinates;
+
+ internal Coordinates SectorCoordinates { get; private set; }
+
+ internal string Condition => GetCondition();
+
+ internal LibraryComputer Computer => (LibraryComputer)_commandExecutors[Command.COM];
+
+ internal ShieldControl ShieldControl => (ShieldControl)_commandExecutors[Command.SHE];
+
+ internal float Energy => TotalEnergy - ShieldControl.ShieldEnergy;
+
+ internal float TotalEnergy { get; private set; }
+
+ internal int DamagedSystemCount => _systems.Count(s => s.IsDamaged);
+
+ internal IEnumerable Systems => _systems;
+
+ internal PhotonTubes PhotonTubes => (PhotonTubes)_commandExecutors[Command.TOR];
+
+ internal bool IsDocked => _quadrant.EnterpriseIsNextToStarbase;
+
+ internal bool IsStranded => TotalEnergy < 10 || Energy < 10 && ShieldControl.IsDamaged;
+
+ internal Enterprise Add(Subsystem system)
+ {
+ _systems.Add(system);
+ _commandExecutors[system.Command] = system;
+
+ return this;
+ }
+
+ internal void StartIn(Quadrant quadrant)
+ {
+ _quadrant = quadrant;
+ quadrant.Display(Strings.StartText);
+ }
+
+ private string GetCondition() =>
+ IsDocked switch
+ {
+ true => "Docked",
+ false when _quadrant.HasKlingons => "*Red*",
+ false when Energy / _maxEnergy < 0.1f => "Yellow",
+ false => "Green"
+ };
+
+ internal CommandResult Execute(Command command)
+ {
+ if (command == Command.XXX) { return CommandResult.GameOver; }
+
+ return _commandExecutors[command].ExecuteCommand(_quadrant);
+ }
+
+ internal void Refuel() => TotalEnergy = _maxEnergy;
+
+ public override string ToString() => "<*>";
+
+ internal void UseEnergy(float amountUsed)
+ {
+ TotalEnergy -= amountUsed;
+ }
+
+ internal CommandResult TakeHit(Coordinates sector, int hitStrength)
+ {
+ _io.WriteLine($"{hitStrength} unit hit on Enterprise from sector {sector}");
+ ShieldControl.AbsorbHit(hitStrength);
+
+ if (ShieldControl.ShieldEnergy <= 0)
+ {
+ _io.WriteLine(Strings.Destroyed);
+ return CommandResult.GameOver;
+ }
+
+ _io.WriteLine($" ");
+
+ if (hitStrength >= 20)
+ {
+ TakeDamage(hitStrength);
+ }
+
+ return CommandResult.Ok;
+ }
+
+ private void TakeDamage(float hitStrength)
+ {
+ var hitShieldRatio = hitStrength / ShieldControl.ShieldEnergy;
+ if (_random.NextFloat() > 0.6 || hitShieldRatio <= 0.02f)
+ {
+ return;
+ }
+
+ var system = _systems[_random.Next1To8Inclusive() - 1];
+ system.TakeDamage(hitShieldRatio + 0.5f * _random.NextFloat());
+ _io.WriteLine($"Damage Control reports, '{system.Name} damaged by the hit.'");
+ }
+
+ internal void RepairSystems(float repairWorkDone)
+ {
+ var repairedSystems = new List();
+
+ foreach (var system in _systems.Where(s => s.IsDamaged))
+ {
+ if (system.Repair(repairWorkDone))
+ {
+ repairedSystems.Add(system.Name);
+ }
+ }
+
+ if (repairedSystems.Any())
+ {
+ _io.WriteLine("Damage Control report:");
+ foreach (var systemName in repairedSystems)
+ {
+ _io.WriteLine($" {systemName} repair completed.");
+ }
+ }
+ }
+
+ internal void VaryConditionOfRandomSystem()
+ {
+ if (_random.NextFloat() > 0.2f) { return; }
+
+ var system = _systems[_random.Next1To8Inclusive() - 1];
+ _io.Write($"Damage Control report: {system.Name} ");
+ if (_random.NextFloat() >= 0.6)
+ {
+ system.Repair(_random.NextFloat() * 3 + 1);
+ _io.WriteLine("state of repair improved");
+ }
+ else
+ {
+ system.TakeDamage(_random.NextFloat() * 5 + 1);
+ _io.WriteLine("damaged");
+ }
+ }
+
+ internal float Move(Course course, float warpFactor, int distance)
+ {
+ var (quadrant, sector) = MoveWithinQuadrant(course, distance) ?? MoveBeyondQuadrant(course, distance);
+
+ if (quadrant != _quadrant.Coordinates)
+ {
+ _quadrant = new Quadrant(_quadrant.Galaxy[quadrant], this, _random, _quadrant.Galaxy, _io);
+ }
+ _quadrant.SetEnterpriseSector(sector);
+ SectorCoordinates = sector;
+
+ TotalEnergy -= distance + 10;
+ if (Energy < 0)
+ {
+ _io.WriteLine("Shield Control supplies energy to complete the maneuver.");
+ ShieldControl.ShieldEnergy = Math.Max(0, TotalEnergy);
+ }
+
+ return GetTimeElapsed(quadrant, warpFactor);
+ }
+
+ private (Coordinates, Coordinates)? MoveWithinQuadrant(Course course, int distance)
+ {
+ var currentSector = SectorCoordinates;
+ foreach (var (sector, index) in course.GetSectorsFrom(SectorCoordinates).Select((s, i) => (s, i)))
+ {
+ if (distance == 0) { break; }
+
+ if (_quadrant.HasObjectAt(sector))
+ {
+ _io.WriteLine($"Warp engines shut down at sector {currentSector} dues to bad navigation");
+ distance = 0;
+ break;
+ }
+
+ currentSector = sector;
+ distance -= 1;
+ }
+
+ return distance == 0 ? (_quadrant.Coordinates, currentSector) : null;
+ }
+
+ private (Coordinates, Coordinates) MoveBeyondQuadrant(Course course, int distance)
+ {
+ var (complete, quadrant, sector) = course.GetDestination(QuadrantCoordinates, SectorCoordinates, distance);
+
+ if (!complete)
+ {
+ _io.Write(Strings.PermissionDenied, sector, quadrant);
+ }
+
+ return (quadrant, sector);
+ }
+
+ private float GetTimeElapsed(Coordinates finalQuadrant, float warpFactor) =>
+ finalQuadrant == _quadrant.Coordinates
+ ? Math.Min(1, (float)Math.Round(warpFactor, 1, MidpointRounding.ToZero))
+ : 1;
}
diff --git a/84_Super_Star_Trek/csharp/Objects/Klingon.cs b/84_Super_Star_Trek/csharp/Objects/Klingon.cs
index 1b55940a..7e84ae56 100644
--- a/84_Super_Star_Trek/csharp/Objects/Klingon.cs
+++ b/84_Super_Star_Trek/csharp/Objects/Klingon.cs
@@ -1,43 +1,43 @@
+using Games.Common.Randomness;
using SuperStarTrek.Commands;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Objects
+namespace SuperStarTrek.Objects;
+
+internal class Klingon
{
- internal class Klingon
+ private readonly IRandom _random;
+
+ internal Klingon(Coordinates sector, IRandom random)
{
- private readonly Random _random;
-
- internal Klingon(Coordinates sector, Random random)
- {
- Sector = sector;
- _random = random;
- Energy = _random.GetFloat(100, 300);
- }
-
- internal float Energy { get; private set; }
-
- internal Coordinates Sector { get; private set; }
-
- public override string ToString() => "+K+";
-
- internal CommandResult FireOn(Enterprise enterprise)
- {
- var attackStrength = _random.GetFloat();
- var distanceToEnterprise = Sector.GetDistanceTo(enterprise.SectorCoordinates);
- var hitStrength = (int)(Energy * (2 + attackStrength) / distanceToEnterprise);
- Energy /= 3 + attackStrength;
-
- return enterprise.TakeHit(Sector, hitStrength);
- }
-
- internal bool TakeHit(int hitStrength)
- {
- if (hitStrength < 0.15 * Energy) { return false; }
-
- Energy -= hitStrength;
- return true;
- }
-
- internal void MoveTo(Coordinates newSector) => Sector = newSector;
+ Sector = sector;
+ _random = random;
+ Energy = _random.NextFloat(100, 300);
}
+
+ internal float Energy { get; private set; }
+
+ internal Coordinates Sector { get; private set; }
+
+ public override string ToString() => "+K+";
+
+ internal CommandResult FireOn(Enterprise enterprise)
+ {
+ var attackStrength = _random.NextFloat();
+ var distanceToEnterprise = Sector.GetDistanceTo(enterprise.SectorCoordinates);
+ var hitStrength = (int)(Energy * (2 + attackStrength) / distanceToEnterprise);
+ Energy /= 3 + attackStrength;
+
+ return enterprise.TakeHit(Sector, hitStrength);
+ }
+
+ internal bool TakeHit(int hitStrength)
+ {
+ if (hitStrength < 0.15 * Energy) { return false; }
+
+ Energy -= hitStrength;
+ return true;
+ }
+
+ internal void MoveTo(Coordinates newSector) => Sector = newSector;
}
diff --git a/84_Super_Star_Trek/csharp/Objects/Star.cs b/84_Super_Star_Trek/csharp/Objects/Star.cs
index 1d9eef6f..8676d3c3 100644
--- a/84_Super_Star_Trek/csharp/Objects/Star.cs
+++ b/84_Super_Star_Trek/csharp/Objects/Star.cs
@@ -1,7 +1,6 @@
-namespace SuperStarTrek.Objects
+namespace SuperStarTrek.Objects;
+
+internal class Star
{
- internal class Star
- {
- public override string ToString() => " * ";
- }
+ public override string ToString() => " * ";
}
diff --git a/84_Super_Star_Trek/csharp/Objects/Starbase.cs b/84_Super_Star_Trek/csharp/Objects/Starbase.cs
index c9abb870..f9e5eaec 100644
--- a/84_Super_Star_Trek/csharp/Objects/Starbase.cs
+++ b/84_Super_Star_Trek/csharp/Objects/Starbase.cs
@@ -1,45 +1,44 @@
+using Games.Common.IO;
+using Games.Common.Randomness;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Objects
+namespace SuperStarTrek.Objects;
+
+internal class Starbase
{
- internal class Starbase
+ private readonly IReadWrite _io;
+ private readonly float _repairDelay;
+
+ internal Starbase(Coordinates sector, IRandom random, IReadWrite io)
{
- private readonly Input _input;
- private readonly Output _output;
- private readonly float _repairDelay;
-
- internal Starbase(Coordinates sector, Random random, Input input, Output output)
- {
- Sector = sector;
- _repairDelay = random.GetFloat() * 0.5f;
- _input = input;
- _output = output;
- }
-
- internal Coordinates Sector { get; }
-
- public override string ToString() => ">!<";
-
- internal bool TryRepair(Enterprise enterprise, out float repairTime)
- {
- repairTime = enterprise.DamagedSystemCount * 0.1f + _repairDelay;
- if (repairTime >= 1) { repairTime = 0.9f; }
-
- _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;
- }
-
- internal void ProtectEnterprise() => _output.WriteLine(Strings.Protected);
+ Sector = sector;
+ _repairDelay = random.NextFloat(0.5f);
+ _io = io;
}
+
+ internal Coordinates Sector { get; }
+
+ public override string ToString() => ">!<";
+
+ internal bool TryRepair(Enterprise enterprise, out float repairTime)
+ {
+ repairTime = enterprise.DamagedSystemCount * 0.1f + _repairDelay;
+ if (repairTime >= 1) { repairTime = 0.9f; }
+
+ _io.Write(Strings.RepairEstimate, repairTime);
+ if (_io.GetYesNo(Strings.RepairPrompt, IReadWriteExtensions.YesNoMode.TrueOnY))
+ {
+ foreach (var system in enterprise.Systems)
+ {
+ system.Repair();
+ }
+ return true;
+ }
+
+ repairTime = 0;
+ return false;
+ }
+
+ internal void ProtectEnterprise() => _io.WriteLine(Strings.Protected);
}
diff --git a/84_Super_Star_Trek/csharp/Output.cs b/84_Super_Star_Trek/csharp/Output.cs
deleted file mode 100644
index 6a377bce..00000000
--- a/84_Super_Star_Trek/csharp/Output.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-
-namespace SuperStarTrek
-{
- internal class Output
- {
- internal Output Write(string text)
- {
- Console.Write(text);
- return this;
- }
-
- internal Output Write(string format, params object[] args)
- {
- Console.Write(format, args);
- return this;
- }
-
- internal Output WriteLine(string text = "")
- {
- Console.WriteLine(text);
- return this;
- }
-
-
- internal Output NextLine()
- {
- Console.WriteLine();
- return this;
- }
-
-
- internal Output Prompt(string text = "")
- {
- Console.Write($"{text}? ");
- return this;
- }
-
- }
-}
diff --git a/84_Super_Star_Trek/csharp/Program.cs b/84_Super_Star_Trek/csharp/Program.cs
index 7080df29..730d56d4 100644
--- a/84_Super_Star_Trek/csharp/Program.cs
+++ b/84_Super_Star_Trek/csharp/Program.cs
@@ -23,24 +23,18 @@
// **** CONVERTED TO MICROSOFT C# 2/20/21 BY ANDREW COOPER
// ****
-namespace SuperStarTrek
+using Games.Common.IO;
+using Games.Common.Randomness;
+using SuperStarTrek;
+
+var io = new ConsoleIO();
+var random = new RandomNumberGenerator();
+
+var game = new Game(io, random);
+
+game.DoIntroduction();
+
+do
{
- internal class Program
- {
- static void Main()
- {
- var output = new Output();
- var input = new Input(output);
- var random = new Random();
-
- var game = new Game(output, input, random);
-
- game.DoIntroduction();
-
- do
- {
- game.Play();
- } while (game.Replay());
- }
- }
-}
+ game.Play();
+} while (game.Replay());
diff --git a/84_Super_Star_Trek/csharp/Random.cs b/84_Super_Star_Trek/csharp/Random.cs
deleted file mode 100644
index cd0ef230..00000000
--- a/84_Super_Star_Trek/csharp/Random.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using SuperStarTrek.Space;
-
-namespace SuperStarTrek
-{
- internal class Random
- {
- private readonly System.Random _random = new();
-
- internal Coordinates GetCoordinate() => new Coordinates(Get1To8Inclusive() - 1, Get1To8Inclusive() - 1);
-
- // Duplicates the algorithm used in the original code to get an integer value from 1 to 8, inclusive:
- // 475 DEF FNR(R)=INT(RND(R)*7.98+1.01)
- // Returns a value from 1 to 8, inclusive.
- // Note there's a slight bias away from the extreme values, 1 and 8.
- internal int Get1To8Inclusive() => (int)(GetFloat() * 7.98 + 1.01);
-
- internal int GetInt(int inclusiveMinValue, int exclusiveMaxValue) =>
- _random.Next(inclusiveMinValue, exclusiveMaxValue);
-
- internal float GetFloat() => (float)_random.NextDouble();
-
- internal float GetFloat(float inclusiveMinValue, float exclusiveMaxValue)
- => GetFloat() * (exclusiveMaxValue - inclusiveMinValue) + inclusiveMinValue;
- }
-}
diff --git a/84_Super_Star_Trek/csharp/Resources/CourtMartial.txt b/84_Super_Star_Trek/csharp/Resources/CourtMartial.txt
index a6c5285e..7d05a5b8 100644
--- a/84_Super_Star_Trek/csharp/Resources/CourtMartial.txt
+++ b/84_Super_Star_Trek/csharp/Resources/CourtMartial.txt
@@ -1,3 +1,3 @@
Starfleet Command reviewing your record to consider
-court martial!
+court martial!
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/Enterprise.txt b/84_Super_Star_Trek/csharp/Resources/Enterprise.txt
index a47156a5..4310ca91 100644
--- a/84_Super_Star_Trek/csharp/Resources/Enterprise.txt
+++ b/84_Super_Star_Trek/csharp/Resources/Enterprise.txt
@@ -16,3 +16,9 @@
'----------------'
THE USS ENTERPRISE --- NCC-1701
+
+
+
+
+
+
diff --git a/84_Super_Star_Trek/csharp/Resources/Instructions.txt b/84_Super_Star_Trek/csharp/Resources/Instructions.txt
index 72ded5ce..34b4169c 100644
--- a/84_Super_Star_Trek/csharp/Resources/Instructions.txt
+++ b/84_Super_Star_Trek/csharp/Resources/Instructions.txt
@@ -104,3 +104,4 @@ COM command = Library-Computer
Option 5 = Galactic Region Name Map
This option prints the names of the sixteen major
galactic regions referred to in the game.
+
diff --git a/84_Super_Star_Trek/csharp/Resources/NoEnemyShips.txt b/84_Super_Star_Trek/csharp/Resources/NoEnemyShips.txt
index d4b2efb2..394f1057 100644
--- a/84_Super_Star_Trek/csharp/Resources/NoEnemyShips.txt
+++ b/84_Super_Star_Trek/csharp/Resources/NoEnemyShips.txt
@@ -1,2 +1,2 @@
Science Officer Spock reports, 'Sensors show no enemy ships
- in this quadrant'
+ in this quadrant'
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/NoStarbase.txt b/84_Super_Star_Trek/csharp/Resources/NoStarbase.txt
index 59c991ec..5bb4e5fb 100644
--- a/84_Super_Star_Trek/csharp/Resources/NoStarbase.txt
+++ b/84_Super_Star_Trek/csharp/Resources/NoStarbase.txt
@@ -1 +1 @@
-Mr. Spock reports, 'Sensors show no starbases in this quadrant.'
+Mr. Spock reports, 'Sensors show no starbases in this quadrant.'
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/NowEntering.txt b/84_Super_Star_Trek/csharp/Resources/NowEntering.txt
index 6e770a71..6545f9c4 100644
--- a/84_Super_Star_Trek/csharp/Resources/NowEntering.txt
+++ b/84_Super_Star_Trek/csharp/Resources/NowEntering.txt
@@ -1,2 +1,3 @@
Now entering {0} quadrant . . .
+
diff --git a/84_Super_Star_Trek/csharp/Resources/Orders.txt b/84_Super_Star_Trek/csharp/Resources/Orders.txt
index 7dd142e5..7dc14b24 100644
--- a/84_Super_Star_Trek/csharp/Resources/Orders.txt
+++ b/84_Super_Star_Trek/csharp/Resources/Orders.txt
@@ -3,3 +3,4 @@ Your orders are as follows:
the galaxy before they can attack federation headquarters
on stardate {1}. This gives you {2} days. There {3}
{4} starbase{5} in the galaxy for resupplying your ship.
+
diff --git a/84_Super_Star_Trek/csharp/Resources/Protected.txt b/84_Super_Star_Trek/csharp/Resources/Protected.txt
index fe23b63b..27c4a5f8 100644
--- a/84_Super_Star_Trek/csharp/Resources/Protected.txt
+++ b/84_Super_Star_Trek/csharp/Resources/Protected.txt
@@ -1 +1 @@
-Starbase shields protect the Enterprise
+Starbase shields protect the Enterprise
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/RegionNames.txt b/84_Super_Star_Trek/csharp/Resources/RegionNames.txt
index 7556a9f8..f84fe43b 100644
--- a/84_Super_Star_Trek/csharp/Resources/RegionNames.txt
+++ b/84_Super_Star_Trek/csharp/Resources/RegionNames.txt
@@ -5,4 +5,4 @@
Canopus Aldebaran
Altair Regulus
Sagittarius Arcturus
- Pollux Spica
+ Pollux Spica
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/RelievedOfCommand.txt b/84_Super_Star_Trek/csharp/Resources/RelievedOfCommand.txt
index 31f398ba..8086e3ca 100644
--- a/84_Super_Star_Trek/csharp/Resources/RelievedOfCommand.txt
+++ b/84_Super_Star_Trek/csharp/Resources/RelievedOfCommand.txt
@@ -1,3 +1,3 @@
That does it, Captain!! You are hereby relieved of command
-and sentenced to 99 stardates at hard labor on Cygnus 12!!
+and sentenced to 99 stardates at hard labor on Cygnus 12!!
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/RepairPrompt.txt b/84_Super_Star_Trek/csharp/Resources/RepairPrompt.txt
index 36428e30..feffdb27 100644
--- a/84_Super_Star_Trek/csharp/Resources/RepairPrompt.txt
+++ b/84_Super_Star_Trek/csharp/Resources/RepairPrompt.txt
@@ -1 +1 @@
-Will you authorize the repair order (Y/N)
+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 8f9c2d54..3ca3a102 100644
--- a/84_Super_Star_Trek/csharp/Resources/ReplayPrompt.txt
+++ b/84_Super_Star_Trek/csharp/Resources/ReplayPrompt.txt
@@ -2,4 +2,4 @@
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'
+let him step forward and enter 'Aye'
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/ShieldsDropped.txt b/84_Super_Star_Trek/csharp/Resources/ShieldsDropped.txt
index acc87f59..9135e8b4 100644
--- a/84_Super_Star_Trek/csharp/Resources/ShieldsDropped.txt
+++ b/84_Super_Star_Trek/csharp/Resources/ShieldsDropped.txt
@@ -1 +1 @@
-Shields dropped for docking purposes
+Shields dropped for docking purposes
\ No newline at end of file
diff --git a/84_Super_Star_Trek/csharp/Resources/StartText.txt b/84_Super_Star_Trek/csharp/Resources/StartText.txt
index c599a2e2..3c6028a5 100644
--- a/84_Super_Star_Trek/csharp/Resources/StartText.txt
+++ b/84_Super_Star_Trek/csharp/Resources/StartText.txt
@@ -2,3 +2,4 @@
Your mission begins with your starship located
in the galactic quadrant, '{0}'.
+
diff --git a/84_Super_Star_Trek/csharp/Resources/Title.txt b/84_Super_Star_Trek/csharp/Resources/Title.txt
index edee3578..ccd86774 100644
--- a/84_Super_Star_Trek/csharp/Resources/Title.txt
+++ b/84_Super_Star_Trek/csharp/Resources/Title.txt
@@ -17,3 +17,11 @@
* *
* *
*************************************
+
+
+
+
+
+
+
+
diff --git a/84_Super_Star_Trek/csharp/Space/Coordinates.cs b/84_Super_Star_Trek/csharp/Space/Coordinates.cs
index 4768d2c2..adfda6de 100644
--- a/84_Super_Star_Trek/csharp/Space/Coordinates.cs
+++ b/84_Super_Star_Trek/csharp/Space/Coordinates.cs
@@ -1,70 +1,69 @@
using System;
using SuperStarTrek.Utils;
-namespace SuperStarTrek.Space
+namespace SuperStarTrek.Space;
+
+// Represents the corrdintate of a quadrant in the galaxy, or a sector in a quadrant.
+// Note that the origin is top-left, x increase downwards, and y increases to the right.
+internal record Coordinates
{
- // Represents the corrdintate of a quadrant in the galaxy, or a sector in a quadrant.
- // Note that the origin is top-left, x increase downwards, and y increases to the right.
- internal record Coordinates
+ internal Coordinates(int x, int y)
{
- internal Coordinates(int x, int y)
- {
- X = Validated(x, nameof(x));
- Y = Validated(y, nameof(y));
+ X = Validated(x, nameof(x));
+ Y = Validated(y, nameof(y));
- RegionIndex = (X << 1) + (Y >> 2);
- SubRegionIndex = Y % 4;
+ RegionIndex = (X << 1) + (Y >> 2);
+ SubRegionIndex = Y % 4;
+ }
+
+ internal int X { get; }
+
+ internal int Y { get; }
+
+ internal int RegionIndex { get; }
+
+ internal int SubRegionIndex { get; }
+
+ private static int Validated(int value, string argumentName)
+ {
+ if (value >= 0 && value <= 7) { return value; }
+
+ 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;
}
- internal int X { get; }
+ coordinates = default;
+ return false;
- internal int Y { get; }
+ static int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
+ }
- internal int RegionIndex { get; }
+ internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) =>
+ DirectionAndDistance.From(this).To(destination);
- internal int SubRegionIndex { get; }
-
- private static int Validated(int value, string argumentName)
- {
- if (value >= 0 && value <= 7) { return value; }
-
- 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;
-
- static int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
- }
-
- internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) =>
- DirectionAndDistance.From(this).To(destination);
-
- internal float GetDistanceTo(Coordinates destination)
- {
- var (_, distance) = GetDirectionAndDistanceTo(destination);
- return distance;
- }
+ internal float GetDistanceTo(Coordinates destination)
+ {
+ var (_, distance) = GetDirectionAndDistanceTo(destination);
+ return distance;
}
}
diff --git a/84_Super_Star_Trek/csharp/Space/Course.cs b/84_Super_Star_Trek/csharp/Space/Course.cs
index 6b9dfc31..f411976a 100644
--- a/84_Super_Star_Trek/csharp/Space/Course.cs
+++ b/84_Super_Star_Trek/csharp/Space/Course.cs
@@ -1,98 +1,97 @@
using System;
using System.Collections.Generic;
-namespace SuperStarTrek.Space
+namespace SuperStarTrek.Space;
+
+// Implements the course calculations from the original code:
+// 530 FORI=1TO9:C(I,1)=0:C(I,2)=0:NEXTI
+// 540 C(3,1)=-1:C(2,1)=-1:C(4,1)=-1:C(4,2)=-1:C(5,2)=-1:C(6,2)=-1
+// 600 C(1,2)=1:C(2,2)=1:C(6,1)=1:C(7,1)=1:C(8,1)=1:C(8,2)=1:C(9,2)=1
+//
+// 3110 X1=C(C1,1)+(C(C1+1,1)-C(C1,1))*(C1-INT(C1))
+// 3140 X2=C(C1,2)+(C(C1+1,2)-C(C1,2))*(C1-INT(C1))
+internal class Course
{
- // Implements the course calculations from the original code:
- // 530 FORI=1TO9:C(I,1)=0:C(I,2)=0:NEXTI
- // 540 C(3,1)=-1:C(2,1)=-1:C(4,1)=-1:C(4,2)=-1:C(5,2)=-1:C(6,2)=-1
- // 600 C(1,2)=1:C(2,2)=1:C(6,1)=1:C(7,1)=1:C(8,1)=1:C(8,2)=1:C(9,2)=1
- //
- // 3110 X1=C(C1,1)+(C(C1+1,1)-C(C1,1))*(C1-INT(C1))
- // 3140 X2=C(C1,2)+(C(C1+1,2)-C(C1,2))*(C1-INT(C1))
- internal class Course
+ private static readonly (int DeltaX, int DeltaY)[] cardinals = new[]
{
- private static readonly (int DeltaX, int DeltaY)[] cardinals = new[]
+ (0, 1),
+ (-1, 1),
+ (-1, 0),
+ (-1, -1),
+ (0, -1),
+ (1, -1),
+ (1, 0),
+ (1, 1),
+ (0, 1)
+ };
+
+ internal Course(float direction)
+ {
+ if (direction < 1 || direction > 9)
{
- (0, 1),
- (-1, 1),
- (-1, 0),
- (-1, -1),
- (0, -1),
- (1, -1),
- (1, 0),
- (1, 1),
- (0, 1)
- };
-
- internal Course(float direction)
- {
- if (direction < 1 || direction > 9)
- {
- throw new ArgumentOutOfRangeException(
- nameof(direction),
- direction,
- "Must be between 1 and 9, inclusive.");
- }
-
- var cardinalDirection = (int)(direction - 1) % 8;
- var fractionalDirection = direction - (int)direction;
-
- var baseCardinal = cardinals[cardinalDirection];
- var nextCardinal = cardinals[cardinalDirection + 1];
-
- DeltaX = baseCardinal.DeltaX + (nextCardinal.DeltaX - baseCardinal.DeltaX) * fractionalDirection;
- DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
+ throw new ArgumentOutOfRangeException(
+ nameof(direction),
+ direction,
+ "Must be between 1 and 9, inclusive.");
}
- internal float DeltaX { get; }
+ var cardinalDirection = (int)(direction - 1) % 8;
+ var fractionalDirection = direction - (int)direction;
- internal float DeltaY { get; }
+ var baseCardinal = cardinals[cardinalDirection];
+ var nextCardinal = cardinals[cardinalDirection + 1];
- internal IEnumerable GetSectorsFrom(Coordinates start)
+ DeltaX = baseCardinal.DeltaX + (nextCardinal.DeltaX - baseCardinal.DeltaX) * fractionalDirection;
+ DeltaY = baseCardinal.DeltaY + (nextCardinal.DeltaY - baseCardinal.DeltaY) * fractionalDirection;
+ }
+
+ internal float DeltaX { get; }
+
+ internal float DeltaY { get; }
+
+ internal IEnumerable GetSectorsFrom(Coordinates start)
+ {
+ (float x, float y) = start;
+
+ while(true)
{
- (float x, float y) = start;
+ x += DeltaX;
+ y += DeltaY;
- while(true)
+ if (!Coordinates.TryCreate(x, y, out var coordinates))
{
- x += DeltaX;
- y += DeltaY;
-
- if (!Coordinates.TryCreate(x, y, out var coordinates))
- {
- yield break;
- }
-
- yield return coordinates;
- }
- }
-
- internal (bool, Coordinates, Coordinates) GetDestination(Coordinates quadrant, Coordinates sector, int distance)
- {
- var (xComplete, quadrantX, sectorX) = GetNewCoordinate(quadrant.X, sector.X, DeltaX * distance);
- var (yComplete, quadrantY, sectorY) = GetNewCoordinate(quadrant.Y, sector.Y, DeltaY * distance);
-
- return (xComplete && yComplete, new Coordinates(quadrantX, quadrantY), new Coordinates(sectorX, sectorY));
- }
-
- private static (bool, int, int) GetNewCoordinate(int quadrant, int sector, float sectorsTravelled)
- {
- var galacticCoordinate = quadrant * 8 + sector + sectorsTravelled;
- var newQuadrant = (int)(galacticCoordinate / 8);
- var newSector = (int)(galacticCoordinate - newQuadrant * 8);
-
- if (newSector < 0)
- {
- newQuadrant -= 1;
- newSector += 8;
+ yield break;
}
- return newQuadrant switch
- {
- < 0 => (false, 0, 0),
- > 7 => (false, 7, 7),
- _ => (true, newQuadrant, newSector)
- };
+ yield return coordinates;
}
}
+
+ internal (bool, Coordinates, Coordinates) GetDestination(Coordinates quadrant, Coordinates sector, int distance)
+ {
+ var (xComplete, quadrantX, sectorX) = GetNewCoordinate(quadrant.X, sector.X, DeltaX * distance);
+ var (yComplete, quadrantY, sectorY) = GetNewCoordinate(quadrant.Y, sector.Y, DeltaY * distance);
+
+ return (xComplete && yComplete, new Coordinates(quadrantX, quadrantY), new Coordinates(sectorX, sectorY));
+ }
+
+ private static (bool, int, int) GetNewCoordinate(int quadrant, int sector, float sectorsTravelled)
+ {
+ var galacticCoordinate = quadrant * 8 + sector + sectorsTravelled;
+ var newQuadrant = (int)(galacticCoordinate / 8);
+ var newSector = (int)(galacticCoordinate - newQuadrant * 8);
+
+ if (newSector < 0)
+ {
+ newQuadrant -= 1;
+ newSector += 8;
+ }
+
+ return newQuadrant switch
+ {
+ < 0 => (false, 0, 0),
+ > 7 => (false, 7, 7),
+ _ => (true, newQuadrant, newSector)
+ };
+ }
}
diff --git a/84_Super_Star_Trek/csharp/Space/Galaxy.cs b/84_Super_Star_Trek/csharp/Space/Galaxy.cs
index 0b348b06..d8e990b4 100644
--- a/84_Super_Star_Trek/csharp/Space/Galaxy.cs
+++ b/84_Super_Star_Trek/csharp/Space/Galaxy.cs
@@ -1,64 +1,64 @@
using System.Collections.Generic;
using System.Linq;
+using Games.Common.Randomness;
using SuperStarTrek.Resources;
using static System.StringSplitOptions;
-namespace SuperStarTrek.Space
+namespace SuperStarTrek.Space;
+
+internal class Galaxy
{
- internal class Galaxy
+ private static readonly string[] _regionNames;
+ private static readonly string[] _subRegionIdentifiers;
+ private readonly QuadrantInfo[][] _quadrants;
+
+ static Galaxy()
{
- private static readonly string[] _regionNames;
- private static readonly string[] _subRegionIdentifiers;
- private readonly QuadrantInfo[][] _quadrants;
+ _regionNames = Strings.RegionNames.Split(new[] { ' ', '\n' }, RemoveEmptyEntries | TrimEntries);
+ _subRegionIdentifiers = new[] { "I", "II", "III", "IV" };
+ }
- static Galaxy()
- {
- _regionNames = Strings.RegionNames.Split(new[] { ' ', '\n' }, RemoveEmptyEntries | TrimEntries);
- _subRegionIdentifiers = new[] { "I", "II", "III", "IV" };
- }
-
- internal Galaxy(Random random)
- {
- _quadrants = Enumerable
+ internal Galaxy(IRandom random)
+ {
+ _quadrants = Enumerable
+ .Range(0, 8)
+ .Select(x => Enumerable
.Range(0, 8)
- .Select(x => Enumerable
- .Range(0, 8)
- .Select(y => new Coordinates(x, y))
- .Select(c => QuadrantInfo.Create(c, GetQuadrantName(c), random))
- .ToArray())
- .ToArray();
+ .Select(y => new Coordinates(x, y))
+ .Select(c => QuadrantInfo.Create(c, GetQuadrantName(c), random))
+ .ToArray())
+ .ToArray();
- if (StarbaseCount == 0)
+ if (StarbaseCount == 0)
+ {
+ var randomQuadrant = this[random.NextCoordinate()];
+ randomQuadrant.AddStarbase();
+
+ if (randomQuadrant.KlingonCount < 2)
{
- var randomQuadrant = this[random.GetCoordinate()];
- randomQuadrant.AddStarbase();
-
- if (randomQuadrant.KlingonCount < 2)
- {
- randomQuadrant.AddKlingon();
- }
+ randomQuadrant.AddKlingon();
}
}
-
- internal QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X][coordinate.Y];
-
- internal int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount);
-
- internal int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
-
- internal IEnumerable> Quadrants => _quadrants;
-
- private static string GetQuadrantName(Coordinates coordinates) =>
- $"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}";
-
- internal IEnumerable> GetNeighborhood(Quadrant quadrant) =>
- Enumerable.Range(-1, 3)
- .Select(dx => dx + quadrant.Coordinates.X)
- .Select(x => GetNeighborhoodRow(quadrant, x));
- private IEnumerable GetNeighborhoodRow(Quadrant quadrant, int x) =>
- Enumerable.Range(-1, 3)
- .Select(dy => dy + quadrant.Coordinates.Y)
- .Select(y => y < 0 || y > 7 || x < 0 || x > 7 ? null : _quadrants[x][y]);
}
+
+ internal QuadrantInfo this[Coordinates coordinate] => _quadrants[coordinate.X][coordinate.Y];
+
+ internal int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount);
+
+ internal int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
+
+ internal IEnumerable> Quadrants => _quadrants;
+
+ private static string GetQuadrantName(Coordinates coordinates) =>
+ $"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}";
+
+ internal IEnumerable> GetNeighborhood(Quadrant quadrant) =>
+ Enumerable.Range(-1, 3)
+ .Select(dx => dx + quadrant.Coordinates.X)
+ .Select(x => GetNeighborhoodRow(quadrant, x));
+ private IEnumerable GetNeighborhoodRow(Quadrant quadrant, int x) =>
+ Enumerable.Range(-1, 3)
+ .Select(dy => dy + quadrant.Coordinates.Y)
+ .Select(y => y < 0 || y > 7 || x < 0 || x > 7 ? null : _quadrants[x][y]);
}
diff --git a/84_Super_Star_Trek/csharp/Space/Quadrant.cs b/84_Super_Star_Trek/csharp/Space/Quadrant.cs
index 694f7fc8..ba8f9a99 100644
--- a/84_Super_Star_Trek/csharp/Space/Quadrant.cs
+++ b/84_Super_Star_Trek/csharp/Space/Quadrant.cs
@@ -1,192 +1,192 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Games.Common.IO;
+using Games.Common.Randomness;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
-namespace SuperStarTrek.Space
+namespace SuperStarTrek.Space;
+
+internal class Quadrant
{
- internal class Quadrant
+ private readonly QuadrantInfo _info;
+ private readonly IRandom _random;
+ private readonly Dictionary _sectors;
+ private readonly Enterprise _enterprise;
+ private readonly IReadWrite _io;
+ private bool _entered = false;
+
+ internal Quadrant(
+ QuadrantInfo info,
+ Enterprise enterprise,
+ IRandom random,
+ Galaxy galaxy,
+ IReadWrite io)
{
- private readonly QuadrantInfo _info;
- private readonly Random _random;
- private readonly Dictionary _sectors;
- private readonly Enterprise _enterprise;
- private readonly Output _output;
- private bool _entered = false;
+ _info = info;
+ _random = random;
+ _io = io;
+ Galaxy = galaxy;
- internal Quadrant(
- QuadrantInfo info,
- Enterprise enterprise,
- Random random,
- Galaxy galaxy,
- Input input,
- Output output)
+ info.MarkAsKnown();
+ _sectors = new() { [enterprise.SectorCoordinates] = _enterprise = enterprise };
+ PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
+ if (_info.HasStarbase)
{
- _info = info;
- _random = random;
- _output = output;
- Galaxy = galaxy;
+ Starbase = PositionObject(sector => new Starbase(sector, _random, io));
+ }
+ PositionObject(_ => new Star(), _info.StarCount);
+ }
- info.MarkAsKnown();
- _sectors = new() { [enterprise.SectorCoordinates] = _enterprise = enterprise };
- PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
- if (_info.HasStarbase)
- {
- Starbase = PositionObject(sector => new Starbase(sector, _random, input, output));
- }
- PositionObject(_ => new Star(), _info.StarCount);
+ internal Coordinates Coordinates => _info.Coordinates;
+
+ internal bool HasKlingons => _info.KlingonCount > 0;
+
+ internal int KlingonCount => _info.KlingonCount;
+
+ internal bool HasStarbase => _info.HasStarbase;
+
+ internal Starbase Starbase { get; }
+
+ internal Galaxy Galaxy { get; }
+
+ internal bool EnterpriseIsNextToStarbase =>
+ _info.HasStarbase &&
+ Math.Abs(_enterprise.SectorCoordinates.X - Starbase.Sector.X) <= 1 &&
+ Math.Abs(_enterprise.SectorCoordinates.Y - Starbase.Sector.Y) <= 1;
+
+ internal IEnumerable Klingons => _sectors.Values.OfType();
+
+ public override string ToString() => _info.Name;
+
+ private T PositionObject(Func objectFactory)
+ {
+ var sector = GetRandomEmptySector();
+ _sectors[sector] = objectFactory.Invoke(sector);
+ return (T)_sectors[sector];
+ }
+
+ private void PositionObject(Func objectFactory, int count)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ PositionObject(objectFactory);
+ }
+ }
+
+ internal void Display(string textFormat)
+ {
+ if (!_entered)
+ {
+ _io.Write(textFormat, this);
+ _entered = true;
}
- internal Coordinates Coordinates => _info.Coordinates;
-
- internal bool HasKlingons => _info.KlingonCount > 0;
-
- internal int KlingonCount => _info.KlingonCount;
-
- internal bool HasStarbase => _info.HasStarbase;
-
- internal Starbase Starbase { get; }
-
- internal Galaxy Galaxy { get; }
-
- internal bool EnterpriseIsNextToStarbase =>
- _info.HasStarbase &&
- Math.Abs(_enterprise.SectorCoordinates.X - Starbase.Sector.X) <= 1 &&
- Math.Abs(_enterprise.SectorCoordinates.Y - Starbase.Sector.Y) <= 1;
-
- internal IEnumerable Klingons => _sectors.Values.OfType();
-
- public override string ToString() => _info.Name;
-
- private T PositionObject(Func objectFactory)
+ if (_info.KlingonCount > 0)
{
- var sector = GetRandomEmptySector();
- _sectors[sector] = objectFactory.Invoke(sector);
- return (T)_sectors[sector];
+ _io.Write(Strings.CombatArea);
+ if (_enterprise.ShieldControl.ShieldEnergy <= 200) { _io.Write(Strings.LowShields); }
}
- private void PositionObject(Func objectFactory, int count)
+ _enterprise.Execute(Command.SRS);
+ }
+
+ internal bool HasObjectAt(Coordinates coordinates) => _sectors.ContainsKey(coordinates);
+
+ internal bool TorpedoCollisionAt(Coordinates coordinates, out string message, out bool gameOver)
+ {
+ gameOver = false;
+ message = default;
+
+ switch (_sectors.GetValueOrDefault(coordinates))
{
- for (int i = 0; i < count; i++)
- {
- PositionObject(objectFactory);
- }
+ case Klingon klingon:
+ message = Remove(klingon);
+ 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 void Display(string textFormat)
- {
- if (!_entered)
- {
- _output.Write(textFormat, this);
- _entered = true;
- }
-
- if (_info.KlingonCount > 0)
- {
- _output.Write(Strings.CombatArea);
- if (_enterprise.ShieldControl.ShieldEnergy <= 200) { _output.Write(Strings.LowShields); }
- }
-
- _enterprise.Execute(Command.SRS);
- }
-
- internal bool HasObjectAt(Coordinates coordinates) => _sectors.ContainsKey(coordinates);
-
- internal bool TorpedoCollisionAt(Coordinates coordinates, out string message, out bool gameOver)
- {
- gameOver = false;
- message = default;
-
- switch (_sectors.GetValueOrDefault(coordinates))
- {
- case Klingon klingon:
- message = Remove(klingon);
- 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 string Remove(Klingon klingon)
+ internal string Remove(Klingon klingon)
+ {
+ _sectors.Remove(klingon.Sector);
+ _info.RemoveKlingon();
+ return "*** Klingon destroyed ***";
+ }
+
+ internal CommandResult KlingonsMoveAndFire()
+ {
+ foreach (var klingon in Klingons.ToList())
{
+ var newSector = GetRandomEmptySector();
_sectors.Remove(klingon.Sector);
- _info.RemoveKlingon();
- return "*** Klingon destroyed ***";
+ _sectors[newSector] = klingon;
+ klingon.MoveTo(newSector);
}
- internal CommandResult KlingonsMoveAndFire()
+ return KlingonsFireOnEnterprise();
+ }
+
+ internal CommandResult KlingonsFireOnEnterprise()
+ {
+ if (EnterpriseIsNextToStarbase && Klingons.Any())
{
- foreach (var klingon in Klingons.ToList())
- {
- var newSector = GetRandomEmptySector();
- _sectors.Remove(klingon.Sector);
- _sectors[newSector] = klingon;
- klingon.MoveTo(newSector);
- }
-
- return KlingonsFireOnEnterprise();
- }
-
- 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; }
- }
-
+ Starbase.ProtectEnterprise();
return CommandResult.Ok;
}
- private Coordinates GetRandomEmptySector()
+ foreach (var klingon in Klingons)
{
- while (true)
+ var result = klingon.FireOn(_enterprise);
+ if (result.IsGameOver) { return result; }
+ }
+
+ return CommandResult.Ok;
+ }
+
+ private Coordinates GetRandomEmptySector()
+ {
+ while (true)
+ {
+ var sector = _random.NextCoordinate();
+ if (!_sectors.ContainsKey(sector))
{
- var sector = _random.GetCoordinate();
- if (!_sectors.ContainsKey(sector))
- {
- return sector;
- }
+ return sector;
}
}
+ }
- internal IEnumerable GetDisplayLines() => Enumerable.Range(0, 8).Select(x => GetDisplayLine(x));
+ internal IEnumerable GetDisplayLines() => Enumerable.Range(0, 8).Select(x => GetDisplayLine(x));
- private string GetDisplayLine(int x) =>
- string.Join(
- " ",
- Enumerable
- .Range(0, 8)
- .Select(y => new Coordinates(x, y))
- .Select(c => _sectors.GetValueOrDefault(c))
- .Select(o => o?.ToString() ?? " "));
+ private string GetDisplayLine(int x) =>
+ string.Join(
+ " ",
+ Enumerable
+ .Range(0, 8)
+ .Select(y => new Coordinates(x, y))
+ .Select(c => _sectors.GetValueOrDefault(c))
+ .Select(o => o?.ToString() ?? " "));
- internal void SetEnterpriseSector(Coordinates sector)
- {
- _sectors.Remove(_enterprise.SectorCoordinates);
- _sectors[sector] = _enterprise;
- }
+ internal void SetEnterpriseSector(Coordinates sector)
+ {
+ _sectors.Remove(_enterprise.SectorCoordinates);
+ _sectors[sector] = _enterprise;
}
}
diff --git a/84_Super_Star_Trek/csharp/Space/QuadrantInfo.cs b/84_Super_Star_Trek/csharp/Space/QuadrantInfo.cs
index 6a403c2e..0c0b65a0 100644
--- a/84_Super_Star_Trek/csharp/Space/QuadrantInfo.cs
+++ b/84_Super_Star_Trek/csharp/Space/QuadrantInfo.cs
@@ -1,65 +1,66 @@
-namespace SuperStarTrek.Space
+using Games.Common.Randomness;
+
+namespace SuperStarTrek.Space;
+
+internal class QuadrantInfo
{
- internal class QuadrantInfo
+ private bool _isKnown;
+
+ private QuadrantInfo(Coordinates coordinates, string name, int klingonCount, int starCount, bool hasStarbase)
{
- private bool _isKnown;
-
- private QuadrantInfo(Coordinates coordinates, string name, int klingonCount, int starCount, bool hasStarbase)
- {
- Coordinates = coordinates;
- Name = name;
- KlingonCount = klingonCount;
- StarCount = starCount;
- HasStarbase = hasStarbase;
- }
-
- internal Coordinates Coordinates { get; }
-
- internal string Name { get; }
-
- internal int KlingonCount { get; private set; }
-
- internal bool HasStarbase { get; private set; }
-
- internal int StarCount { get; }
-
- internal static QuadrantInfo Create(Coordinates coordinates, string name, Random random)
- {
- var klingonCount = random.GetFloat() switch
- {
- > 0.98f => 3,
- > 0.95f => 2,
- > 0.80f => 1,
- _ => 0
- };
- var hasStarbase = random.GetFloat() > 0.96f;
- var starCount = random.Get1To8Inclusive();
-
- return new QuadrantInfo(coordinates, name, klingonCount, starCount, hasStarbase);
- }
-
- internal void AddKlingon() => KlingonCount += 1;
-
- internal void AddStarbase() => HasStarbase = true;
-
- internal void MarkAsKnown() => _isKnown = true;
-
- 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;
+ Coordinates = coordinates;
+ Name = name;
+ KlingonCount = klingonCount;
+ StarCount = starCount;
+ HasStarbase = hasStarbase;
}
+
+ internal Coordinates Coordinates { get; }
+
+ internal string Name { get; }
+
+ internal int KlingonCount { get; private set; }
+
+ internal bool HasStarbase { get; private set; }
+
+ internal int StarCount { get; }
+
+ internal static QuadrantInfo Create(Coordinates coordinates, string name, IRandom random)
+ {
+ var klingonCount = random.NextFloat() switch
+ {
+ > 0.98f => 3,
+ > 0.95f => 2,
+ > 0.80f => 1,
+ _ => 0
+ };
+ var hasStarbase = random.NextFloat() > 0.96f;
+ var starCount = random.Next1To8Inclusive();
+
+ return new QuadrantInfo(coordinates, name, klingonCount, starCount, hasStarbase);
+ }
+
+ internal void AddKlingon() => KlingonCount += 1;
+
+ internal void AddStarbase() => HasStarbase = true;
+
+ internal void MarkAsKnown() => _isKnown = true;
+
+ 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;
}
diff --git a/84_Super_Star_Trek/csharp/StringExtensions.cs b/84_Super_Star_Trek/csharp/StringExtensions.cs
index 4e77291a..4706e9cb 100644
--- a/84_Super_Star_Trek/csharp/StringExtensions.cs
+++ b/84_Super_Star_Trek/csharp/StringExtensions.cs
@@ -1,7 +1,6 @@
-namespace SuperStarTrek
+namespace SuperStarTrek;
+
+internal static class StringExtensions
{
- internal static class StringExtensions
- {
- internal static string Pluralize(this string singular, int quantity) => singular + (quantity > 1 ? "s" : "");
- }
+ internal static string Pluralize(this string singular, int quantity) => singular + (quantity > 1 ? "s" : "");
}
diff --git a/84_Super_Star_Trek/csharp/SuperStarTrek.csproj b/84_Super_Star_Trek/csharp/SuperStarTrek.csproj
index c0de0594..de228ec6 100644
--- a/84_Super_Star_Trek/csharp/SuperStarTrek.csproj
+++ b/84_Super_Star_Trek/csharp/SuperStarTrek.csproj
@@ -2,11 +2,15 @@
Exe
- net5.0
+ net6.0
+
+
+
+
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs
index 43553bd7..4356b859 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/ComputerFunction.cs
@@ -1,19 +1,19 @@
+using Games.Common.IO;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal abstract class ComputerFunction
{
- internal abstract class ComputerFunction
+ protected ComputerFunction(string description, IReadWrite io)
{
- protected ComputerFunction(string description, Output output)
- {
- Description = description;
- Output = output;
- }
-
- internal string Description { get; }
-
- protected Output Output { get; }
-
- internal abstract void Execute(Quadrant quadrant);
+ Description = description;
+ IO = io;
}
+
+ internal string Description { get; }
+
+ protected IReadWrite IO { get; }
+
+ internal abstract void Execute(Quadrant quadrant);
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs
index 920fbcca..f7c93f2b 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/CumulativeGalacticRecord.cs
@@ -1,21 +1,24 @@
-using System;
using System.Collections.Generic;
using System.Linq;
+using Games.Common.IO;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal class CumulativeGalacticRecord : GalacticReport
{
- internal class CumulativeGalacticRecord : GalacticReport
+ internal CumulativeGalacticRecord(IReadWrite io, Galaxy galaxy)
+ : base("Cumulative galactic record", io, galaxy)
{
- internal CumulativeGalacticRecord(Output output, Galaxy galaxy)
- : base("Cumulative galactic record", output, galaxy)
- {
- }
-
- protected override void WriteHeader(Quadrant quadrant) =>
- Output.NextLine().WriteLine($"Computer record of galaxy for quadrant {quadrant.Coordinates}").NextLine();
-
- protected override IEnumerable GetRowData() =>
- Galaxy.Quadrants.Select(row => " " + string.Join(" ", row));
}
+
+ protected override void WriteHeader(Quadrant quadrant)
+ {
+ IO.WriteLine();
+ IO.WriteLine($"Computer record of galaxy for quadrant {quadrant.Coordinates}");
+ IO.WriteLine();
+ }
+
+ protected override IEnumerable GetRowData() =>
+ Galaxy.Quadrants.Select(row => " " + string.Join(" ", row));
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs
index 3e9965db..e3402ab2 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/DirectionDistanceCalculator.cs
@@ -1,30 +1,30 @@
+using Games.Common.IO;
using SuperStarTrek.Objects;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal class DirectionDistanceCalculator : NavigationCalculator
{
- internal class DirectionDistanceCalculator : NavigationCalculator
+ private readonly Enterprise _enterprise;
+ private readonly IReadWrite _io;
+
+ internal DirectionDistanceCalculator(Enterprise enterprise, IReadWrite io)
+ : base("Direction/distance calculator", io)
{
- private readonly Enterprise _enterprise;
- private readonly Input _input;
+ _enterprise = enterprise;
+ _io = io;
+ }
- internal DirectionDistanceCalculator(Enterprise enterprise, Output output, Input input)
- : base("Direction/distance calculator", output)
- {
- _enterprise = enterprise;
- _input = input;
- }
+ internal override void Execute(Quadrant quadrant)
+ {
+ IO.WriteLine("Direction/distance calculator:");
+ IO.Write($"You are at quadrant {_enterprise.QuadrantCoordinates}");
+ IO.WriteLine($" sector {_enterprise.SectorCoordinates}");
+ IO.WriteLine("Please enter");
- internal override void Execute(Quadrant quadrant)
- {
- Output.WriteLine("Direction/distance calculator:")
- .Write($"You are at quadrant {_enterprise.QuadrantCoordinates}")
- .WriteLine($" sector {_enterprise.SectorCoordinates}")
- .WriteLine("Please enter");
-
- WriteDirectionAndDistance(
- _input.GetCoordinates(" Initial coordinates"),
- _input.GetCoordinates(" Final coordinates"));
- }
+ WriteDirectionAndDistance(
+ _io.GetCoordinates(" Initial coordinates"),
+ _io.GetCoordinates(" Final coordinates"));
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs
index 1e8d5f23..49f7363d 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalacticReport.cs
@@ -1,34 +1,34 @@
using System.Collections.Generic;
using System.Linq;
+using Games.Common.IO;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal abstract class GalacticReport : ComputerFunction
{
- internal abstract class GalacticReport : ComputerFunction
+ internal GalacticReport(string description, IReadWrite io, Galaxy galaxy)
+ : base(description, io)
{
- internal GalacticReport(string description, Output output, Galaxy galaxy)
- : base(description, output)
+ Galaxy = galaxy;
+ }
+
+ protected Galaxy Galaxy { get; }
+
+ protected abstract void WriteHeader(Quadrant quadrant);
+
+ protected abstract IEnumerable GetRowData();
+
+ internal sealed override void Execute(Quadrant quadrant)
+ {
+ WriteHeader(quadrant);
+ IO.WriteLine(" 1 2 3 4 5 6 7 8");
+ IO.WriteLine(" ----- ----- ----- ----- ----- ----- ----- -----");
+
+ foreach (var (row, index) in GetRowData().Select((r, i) => (r, i)))
{
- Galaxy = galaxy;
- }
-
- protected Galaxy Galaxy { get; }
-
- protected abstract void WriteHeader(Quadrant quadrant);
-
- protected abstract IEnumerable GetRowData();
-
- internal sealed override void Execute(Quadrant quadrant)
- {
- WriteHeader(quadrant);
- Output.WriteLine(" 1 2 3 4 5 6 7 8")
- .WriteLine(" ----- ----- ----- ----- ----- ----- ----- -----");
-
- foreach (var (row, index) in GetRowData().Select((r, i) => (r, i)))
- {
- Output.WriteLine($" {index+1} {row}")
- .WriteLine(" ----- ----- ----- ----- ----- ----- ----- -----");
- }
+ IO.WriteLine($" {index+1} {row}");
+ IO.WriteLine(" ----- ----- ----- ----- ----- ----- ----- -----");
}
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs
index 12ff204b..c4850e1c 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/GalaxyRegionMap.cs
@@ -1,21 +1,21 @@
using System.Collections.Generic;
using System.Linq;
+using Games.Common.IO;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal class GalaxyRegionMap : GalacticReport
{
- internal class GalaxyRegionMap : GalacticReport
+ internal GalaxyRegionMap(IReadWrite io, Galaxy galaxy)
+ : base("Galaxy 'region name' map", io, galaxy)
{
- internal GalaxyRegionMap(Output output, Galaxy galaxy)
- : base("Galaxy 'region name' map", output, galaxy)
- {
- }
-
- protected override void WriteHeader(Quadrant quadrant) =>
- Output.WriteLine(" The Galaxy");
-
- protected override IEnumerable GetRowData() =>
- Strings.RegionNames.Split('\n').Select(n => n.TrimEnd('\r'));
}
+
+ protected override void WriteHeader(Quadrant quadrant) =>
+ IO.WriteLine(" The Galaxy");
+
+ protected override IEnumerable GetRowData() =>
+ Strings.RegionNames.Split('\n').Select(n => n.TrimEnd('\r'));
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs
index ef35f8c3..bddb00d2 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/NavigationCalculator.cs
@@ -1,29 +1,31 @@
+using Games.Common.IO;
using SuperStarTrek.Space;
using SuperStarTrek.Utils;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal abstract class NavigationCalculator : ComputerFunction
{
- internal abstract class NavigationCalculator : ComputerFunction
+ protected NavigationCalculator(string description, IReadWrite io)
+ : base(description, io)
{
- protected NavigationCalculator(string description, Output output)
- : base(description, output)
- {
- }
+ }
- protected void WriteDirectionAndDistance(Coordinates from, Coordinates to)
- {
- var (direction, distance) = from.GetDirectionAndDistanceTo(to);
- Write(direction, distance);
- }
+ protected void WriteDirectionAndDistance(Coordinates from, Coordinates to)
+ {
+ var (direction, distance) = from.GetDirectionAndDistanceTo(to);
+ Write(direction, distance);
+ }
- protected void WriteDirectionAndDistance((float X, float Y) from, (float X, float Y) to)
- {
- var (direction, distance) = DirectionAndDistance.From(from.X, from.Y).To(to.X, to.Y);
- Write(direction, distance);
- }
+ protected void WriteDirectionAndDistance((float X, float Y) from, (float X, float Y) to)
+ {
+ var (direction, distance) = DirectionAndDistance.From(from.X, from.Y).To(to.X, to.Y);
+ Write(direction, distance);
+ }
- private void Write(float direction, float distance) =>
- Output.WriteLine($"Direction = {direction}")
- .WriteLine($"Distance = {distance}");
+ private void Write(float direction, float distance)
+ {
+ IO.WriteLine($"Direction = {direction}");
+ IO.WriteLine($"Distance = {distance}");
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs
index 07f2119b..08e7eda3 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StarbaseDataCalculator.cs
@@ -1,30 +1,30 @@
+using Games.Common.IO;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal class StarbaseDataCalculator : NavigationCalculator
{
- internal class StarbaseDataCalculator : NavigationCalculator
+ private readonly Enterprise _enterprise;
+
+ internal StarbaseDataCalculator(Enterprise enterprise, IReadWrite io)
+ : base("Starbase nav data", io)
{
- private readonly Enterprise _enterprise;
+ _enterprise = enterprise;
+ }
- internal StarbaseDataCalculator(Enterprise enterprise, Output output)
- : base("Starbase nav data", output)
+ internal override void Execute(Quadrant quadrant)
+ {
+ if (!quadrant.HasStarbase)
{
- _enterprise = enterprise;
+ IO.WriteLine(Strings.NoStarbase);
+ return;
}
- internal override void Execute(Quadrant quadrant)
- {
- if (!quadrant.HasStarbase)
- {
- Output.WriteLine(Strings.NoStarbase);
- return;
- }
+ IO.WriteLine("From Enterprise to Starbase:");
- Output.WriteLine("From Enterprise to Starbase:");
-
- WriteDirectionAndDistance(_enterprise.SectorCoordinates, quadrant.Starbase.Sector);
- }
+ WriteDirectionAndDistance(_enterprise.SectorCoordinates, quadrant.Starbase.Sector);
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StatusReport.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StatusReport.cs
index 6e6bf6f1..b0d6bc1d 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StatusReport.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/StatusReport.cs
@@ -1,41 +1,43 @@
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
+namespace SuperStarTrek.Systems.ComputerFunctions;
+
+internal class StatusReport : ComputerFunction
{
- internal class StatusReport : ComputerFunction
+ private readonly Game _game;
+ private readonly Galaxy _galaxy;
+ private readonly Enterprise _enterprise;
+
+ internal StatusReport(Game game, Galaxy galaxy, Enterprise enterprise, IReadWrite io)
+ : base("Status report", io)
{
- private readonly Game _game;
- private readonly Galaxy _galaxy;
- private readonly Enterprise _enterprise;
+ _game = game;
+ _galaxy = galaxy;
+ _enterprise = enterprise;
+ }
- internal StatusReport(Game game, Galaxy galaxy, Enterprise enterprise, Output output)
- : base("Status report", output)
+ internal override void Execute(Quadrant quadrant)
+ {
+ IO.WriteLine(" Status report:");
+ IO.Write("Klingon".Pluralize(_galaxy.KlingonCount));
+ IO.WriteLine($" left: {_galaxy.KlingonCount}");
+ IO.WriteLine($"Mission must be completed in {_game.StardatesRemaining:0.#} stardates.");
+
+ if (_galaxy.StarbaseCount > 0)
{
- _game = game;
- _galaxy = galaxy;
- _enterprise = enterprise;
+ IO.Write($"The Federation is maintaining {_galaxy.StarbaseCount} ");
+ IO.Write("starbase".Pluralize(_galaxy.StarbaseCount));
+ IO.WriteLine(" in the galaxy.");
+ }
+ else
+ {
+ IO.WriteLine("Your stupidity has left you on your own in");
+ IO.WriteLine(" the galaxy -- you have no starbases left!");
}
- internal override void Execute(Quadrant quadrant)
- {
- Output.WriteLine(" Status report:")
- .Write("Klingon".Pluralize(_galaxy.KlingonCount)).WriteLine($" left: {_galaxy.KlingonCount}")
- .WriteLine($"Mission must be completed in {_game.StardatesRemaining:0.#} stardates.");
-
- if (_galaxy.StarbaseCount > 0)
- {
- Output.Write($"The Federation is maintaining {_galaxy.StarbaseCount} ")
- .Write("starbase".Pluralize(_galaxy.StarbaseCount)).WriteLine(" in the galaxy.");
- }
- else
- {
- Output.WriteLine("Your stupidity has left you on your own in")
- .WriteLine(" the galaxy -- you have no starbases left!");
- }
-
- _enterprise.Execute(Command.DAM);
- }
+ _enterprise.Execute(Command.DAM);
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs
index 94f8ae9a..d1de3eb7 100644
--- a/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ComputerFunctions/TorpedoDataCalculator.cs
@@ -1,33 +1,33 @@
+using Games.Common.IO;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems.ComputerFunctions
-{
- internal class TorpedoDataCalculator : NavigationCalculator
- {
- private readonly Enterprise _enterprise;
+namespace SuperStarTrek.Systems.ComputerFunctions;
- internal TorpedoDataCalculator(Enterprise enterprise, Output output)
- : base("Photon torpedo data", output)
+internal class TorpedoDataCalculator : NavigationCalculator
+{
+ private readonly Enterprise _enterprise;
+
+ internal TorpedoDataCalculator(Enterprise enterprise, IReadWrite io)
+ : base("Photon torpedo data", io)
+ {
+ _enterprise = enterprise;
+ }
+
+ internal override void Execute(Quadrant quadrant)
+ {
+ if (!quadrant.HasKlingons)
{
- _enterprise = enterprise;
+ IO.WriteLine(Strings.NoEnemyShips);
+ return;
}
- internal override void Execute(Quadrant quadrant)
+ IO.WriteLine("From Enterprise to Klingon battle cruiser".Pluralize(quadrant.KlingonCount));
+
+ foreach (var klingon in quadrant.Klingons)
{
- if (!quadrant.HasKlingons)
- {
- Output.WriteLine(Strings.NoEnemyShips);
- return;
- }
-
- Output.WriteLine("From Enterprise to Klingon battle cruiser".Pluralize(quadrant.KlingonCount));
-
- foreach (var klingon in quadrant.Klingons)
- {
- WriteDirectionAndDistance(_enterprise.SectorCoordinates, klingon.Sector);
- }
+ WriteDirectionAndDistance(_enterprise.SectorCoordinates, klingon.Sector);
}
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/DamageControl.cs b/84_Super_Star_Trek/csharp/Systems/DamageControl.cs
index 8fbf21d3..53dc586e 100644
--- a/84_Super_Star_Trek/csharp/Systems/DamageControl.cs
+++ b/84_Super_Star_Trek/csharp/Systems/DamageControl.cs
@@ -1,54 +1,55 @@
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class DamageControl : Subsystem
{
- internal class DamageControl : Subsystem
+ private readonly Enterprise _enterprise;
+ private readonly IReadWrite _io;
+
+ internal DamageControl(Enterprise enterprise, IReadWrite io)
+ : base("Damage Control", Command.DAM, io)
{
- private readonly Enterprise _enterprise;
- private readonly Output _output;
+ _enterprise = enterprise;
+ _io = io;
+ }
- internal DamageControl(Enterprise enterprise, Output output)
- : base("Damage Control", Command.DAM, output)
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ if (IsDamaged)
{
- _enterprise = enterprise;
- _output = output;
+ _io.WriteLine("Damage Control report not available");
+ }
+ else
+ {
+ _io.WriteLine();
+ WriteDamageReport();
}
- protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ if (_enterprise.DamagedSystemCount > 0 && _enterprise.IsDocked)
{
- if (IsDamaged)
+ if (quadrant.Starbase.TryRepair(_enterprise, out var repairTime))
{
- _output.WriteLine("Damage Control report not available");
- }
- else
- {
- _output.NextLine();
WriteDamageReport();
+ return CommandResult.Elapsed(repairTime);
}
-
- if (_enterprise.DamagedSystemCount > 0 && _enterprise.IsDocked)
- {
- if (quadrant.Starbase.TryRepair(_enterprise, out var repairTime))
- {
- WriteDamageReport();
- return CommandResult.Elapsed(repairTime);
- }
- }
-
- return CommandResult.Ok;
}
- internal void WriteDamageReport()
+ return CommandResult.Ok;
+ }
+
+ internal void WriteDamageReport()
+ {
+ _io.WriteLine();
+ _io.WriteLine("Device State of Repair");
+ foreach (var system in _enterprise.Systems)
{
- _output.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();
+ _io.Write(system.Name.PadRight(25));
+ _io.WriteLine((int)(system.Condition * 100) * 0.01F);
}
+ _io.WriteLine();
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/LibraryComputer.cs b/84_Super_Star_Trek/csharp/Systems/LibraryComputer.cs
index df5c6868..4a56909e 100644
--- a/84_Super_Star_Trek/csharp/Systems/LibraryComputer.cs
+++ b/84_Super_Star_Trek/csharp/Systems/LibraryComputer.cs
@@ -1,46 +1,44 @@
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Space;
using SuperStarTrek.Systems.ComputerFunctions;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class LibraryComputer : Subsystem
{
- internal class LibraryComputer : Subsystem
+ private readonly IReadWrite _io;
+ private readonly ComputerFunction[] _functions;
+
+ internal LibraryComputer(IReadWrite io, params ComputerFunction[] functions)
+ : base("Library-Computer", Command.COM, io)
{
- private readonly Output _output;
- private readonly Input _input;
- private readonly ComputerFunction[] _functions;
+ _io = io;
+ _functions = functions;
+ }
- internal LibraryComputer(Output output, Input input, params ComputerFunction[] functions)
- : base("Library-Computer", Command.COM, output)
+ protected override bool CanExecuteCommand() => IsOperational("Computer disabled");
+
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ var index = GetFunctionIndex();
+ _io.WriteLine();
+
+ _functions[index].Execute(quadrant);
+
+ return CommandResult.Ok;
+ }
+
+ private int GetFunctionIndex()
+ {
+ while (true)
{
- _output = output;
- _input = input;
- _functions = functions;
- }
+ var index = (int)_io.ReadNumber("Computer active and waiting command");
+ if (index >= 0 && index <= 5) { return index; }
- protected override bool CanExecuteCommand() => IsOperational("Computer disabled");
-
- protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
- {
- var index = GetFunctionIndex();
- _output.NextLine();
-
- _functions[index].Execute(quadrant);
-
- return CommandResult.Ok;
- }
-
- private int GetFunctionIndex()
- {
- while (true)
+ for (int i = 0; i < _functions.Length; i++)
{
- var index = (int)_input.GetNumber("Computer active and waiting command");
- if (index >= 0 && index <= 5) { return index; }
-
- for (int i = 0; i < _functions.Length; i++)
- {
- _output.WriteLine($" {i} = {_functions[i].Description}");
- }
+ _io.WriteLine($" {i} = {_functions[i].Description}");
}
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/LongRangeSensors.cs b/84_Super_Star_Trek/csharp/Systems/LongRangeSensors.cs
index a873eeba..2e21b63c 100644
--- a/84_Super_Star_Trek/csharp/Systems/LongRangeSensors.cs
+++ b/84_Super_Star_Trek/csharp/Systems/LongRangeSensors.cs
@@ -1,34 +1,35 @@
using System.Linq;
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class LongRangeSensors : Subsystem
{
- internal class LongRangeSensors : Subsystem
+ private readonly Galaxy _galaxy;
+ private readonly IReadWrite _io;
+
+ internal LongRangeSensors(Galaxy galaxy, IReadWrite io)
+ : base("Long Range Sensors", Command.LRS, io)
{
- private readonly Galaxy _galaxy;
- private readonly Output _output;
+ _galaxy = galaxy;
+ _io = io;
+ }
- internal LongRangeSensors(Galaxy galaxy, Output output)
- : base("Long Range Sensors", Command.LRS, output)
+ protected override bool CanExecuteCommand() => IsOperational("{name} are inoperable");
+
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ _io.WriteLine($"Long range scan for quadrant {quadrant.Coordinates}");
+ _io.WriteLine("-------------------");
+ foreach (var quadrants in _galaxy.GetNeighborhood(quadrant))
{
- _galaxy = galaxy;
- _output = output;
+ _io.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
+ _io.WriteLine("-------------------");
}
- 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("-------------------");
- foreach (var quadrants in _galaxy.GetNeighborhood(quadrant))
- {
- _output.WriteLine(": " + string.Join(" : ", quadrants.Select(q => q?.Scan() ?? "***")) + " :");
- _output.WriteLine("-------------------");
- }
-
- return CommandResult.Ok;
- }
+ return CommandResult.Ok;
}
}
+
diff --git a/84_Super_Star_Trek/csharp/Systems/PhaserControl.cs b/84_Super_Star_Trek/csharp/Systems/PhaserControl.cs
index 9207ad94..61249d51 100644
--- a/84_Super_Star_Trek/csharp/Systems/PhaserControl.cs
+++ b/84_Super_Star_Trek/csharp/Systems/PhaserControl.cs
@@ -1,97 +1,96 @@
using System.Linq;
+using Games.Common.IO;
+using Games.Common.Randomness;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class PhaserControl : Subsystem
{
- internal class PhaserControl : Subsystem
+ private readonly Enterprise _enterprise;
+ private readonly IReadWrite _io;
+ private readonly IRandom _random;
+
+ internal PhaserControl(Enterprise enterprise, IReadWrite io, IRandom random)
+ : base("Phaser Control", Command.PHA, io)
{
- private readonly Enterprise _enterprise;
- private readonly Output _output;
- private readonly Input _input;
- private readonly Random _random;
+ _enterprise = enterprise;
+ _io = io;
+ _random = random;
+ }
- internal PhaserControl(Enterprise enterprise, Output output, Input input, Random random)
- : base("Phaser Control", Command.PHA, output)
+ protected override bool CanExecuteCommand() => IsOperational("Phasers inoperative");
+
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ if (!quadrant.HasKlingons)
{
- _enterprise = enterprise;
- _output = output;
- _input = input;
- _random = random;
+ _io.WriteLine(Strings.NoEnemyShips);
+ return CommandResult.Ok;
}
- protected override bool CanExecuteCommand() => IsOperational("Phasers inoperative");
-
- protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ if (_enterprise.Computer.IsDamaged)
{
- if (!quadrant.HasKlingons)
- {
- _output.WriteLine(Strings.NoEnemyShips);
- return CommandResult.Ok;
- }
-
- if (_enterprise.Computer.IsDamaged)
- {
- _output.WriteLine("Computer failure hampers accuracy");
- }
-
- _output.Write($"Phasers locked on target; ");
-
- var phaserStrength = GetPhaserStrength();
- if (phaserStrength < 0) { return CommandResult.Ok; }
-
- _enterprise.UseEnergy(phaserStrength);
-
- var perEnemyStrength = GetPerTargetPhaserStrength(phaserStrength, quadrant.KlingonCount);
-
- foreach (var klingon in quadrant.Klingons.ToList())
- {
- ResolveHitOn(klingon, perEnemyStrength, quadrant);
- }
-
- return quadrant.KlingonsFireOnEnterprise();
+ _io.WriteLine("Computer failure hampers accuracy");
}
- private float GetPhaserStrength()
- {
- while (true)
- {
- _output.WriteLine($"Energy available = {_enterprise.Energy} units");
- var phaserStrength = _input.GetNumber("Number of units to fire");
+ _io.Write($"Phasers locked on target; ");
- if (phaserStrength <= _enterprise.Energy) { return phaserStrength; }
- }
+ var phaserStrength = GetPhaserStrength();
+ if (phaserStrength < 0) { return CommandResult.Ok; }
+
+ _enterprise.UseEnergy(phaserStrength);
+
+ var perEnemyStrength = GetPerTargetPhaserStrength(phaserStrength, quadrant.KlingonCount);
+
+ foreach (var klingon in quadrant.Klingons.ToList())
+ {
+ ResolveHitOn(klingon, perEnemyStrength, quadrant);
}
- private float GetPerTargetPhaserStrength(float phaserStrength, int targetCount)
- {
- if (_enterprise.Computer.IsDamaged)
- {
- phaserStrength *= _random.GetFloat();
- }
+ return quadrant.KlingonsFireOnEnterprise();
+ }
- return phaserStrength / targetCount;
+ private float GetPhaserStrength()
+ {
+ while (true)
+ {
+ _io.WriteLine($"Energy available = {_enterprise.Energy} units");
+ var phaserStrength = _io.ReadNumber("Number of units to fire");
+
+ if (phaserStrength <= _enterprise.Energy) { return phaserStrength; }
+ }
+ }
+
+ private float GetPerTargetPhaserStrength(float phaserStrength, int targetCount)
+ {
+ if (_enterprise.Computer.IsDamaged)
+ {
+ phaserStrength *= _random.NextFloat();
}
- private void ResolveHitOn(Klingon klingon, float perEnemyStrength, Quadrant quadrant)
- {
- var distance = _enterprise.SectorCoordinates.GetDistanceTo(klingon.Sector);
- var hitStrength = (int)(perEnemyStrength / distance * (2 + _random.GetFloat()));
+ return phaserStrength / targetCount;
+ }
- if (klingon.TakeHit(hitStrength))
- {
- _output.WriteLine($"{hitStrength} unit hit on Klingon at sector {klingon.Sector}");
- _output.WriteLine(
- klingon.Energy <= 0
- ? quadrant.Remove(klingon)
- : $" (sensors show {klingon.Energy} units remaining)");
- }
- else
- {
- _output.WriteLine($"Sensors show no damage to enemy at {klingon.Sector}");
- }
+ private void ResolveHitOn(Klingon klingon, float perEnemyStrength, Quadrant quadrant)
+ {
+ var distance = _enterprise.SectorCoordinates.GetDistanceTo(klingon.Sector);
+ var hitStrength = (int)(perEnemyStrength / distance * (2 + _random.NextFloat()));
+
+ if (klingon.TakeHit(hitStrength))
+ {
+ _io.WriteLine($"{hitStrength} unit hit on Klingon at sector {klingon.Sector}");
+ _io.WriteLine(
+ klingon.Energy <= 0
+ ? quadrant.Remove(klingon)
+ : $" (sensors show {klingon.Energy} units remaining)");
+ }
+ else
+ {
+ _io.WriteLine($"Sensors show no damage to enemy at {klingon.Sector}");
}
}
}
diff --git a/84_Super_Star_Trek/csharp/Systems/PhotonTubes.cs b/84_Super_Star_Trek/csharp/Systems/PhotonTubes.cs
index 37613037..597ae3a0 100644
--- a/84_Super_Star_Trek/csharp/Systems/PhotonTubes.cs
+++ b/84_Super_Star_Trek/csharp/Systems/PhotonTubes.cs
@@ -1,66 +1,64 @@
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class PhotonTubes : Subsystem
{
- internal class PhotonTubes : Subsystem
+ private readonly int _tubeCount;
+ private readonly Enterprise _enterprise;
+ private readonly IReadWrite _io;
+
+ internal PhotonTubes(int tubeCount, Enterprise enterprise, IReadWrite io)
+ : base("Photon Tubes", Command.TOR, io)
{
- private readonly int _tubeCount;
- private readonly Enterprise _enterprise;
- private readonly Output _output;
- private readonly Input _input;
-
- internal PhotonTubes(int tubeCount, Enterprise enterprise, Output output, Input input)
- : base("Photon Tubes", Command.TOR, output)
- {
- TorpedoCount = _tubeCount = tubeCount;
- _enterprise = enterprise;
- _output = output;
- _input = input;
- }
-
- internal 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.TryGetCourse("Photon torpedo course", "Ensign Chekov", out var course))
- {
- return CommandResult.Ok;
- }
-
- TorpedoCount -= 1;
-
- var isHit = false;
- _output.WriteLine("Torpedo track:");
- foreach (var sector in course.GetSectorsFrom(_enterprise.SectorCoordinates))
- {
- _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();
- }
-
- internal void ReplenishTorpedoes() => TorpedoCount = _tubeCount;
+ TorpedoCount = _tubeCount = tubeCount;
+ _enterprise = enterprise;
+ _io = io;
}
+
+ internal int TorpedoCount { get; private set; }
+
+ protected override bool CanExecuteCommand() => HasTorpedoes() && IsOperational("{name} are not operational");
+
+ private bool HasTorpedoes()
+ {
+ if (TorpedoCount > 0) { return true; }
+
+ _io.WriteLine("All photon torpedoes expended");
+ return false;
+ }
+
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ if (!_io.TryReadCourse("Photon torpedo course", "Ensign Chekov", out var course))
+ {
+ return CommandResult.Ok;
+ }
+
+ TorpedoCount -= 1;
+
+ var isHit = false;
+ _io.WriteLine("Torpedo track:");
+ foreach (var sector in course.GetSectorsFrom(_enterprise.SectorCoordinates))
+ {
+ _io.WriteLine($" {sector}");
+
+ if (quadrant.TorpedoCollisionAt(sector, out var message, out var gameOver))
+ {
+ _io.WriteLine(message);
+ isHit = true;
+ if (gameOver) { return CommandResult.GameOver; }
+ break;
+ }
+ }
+
+ if (!isHit) { _io.WriteLine("Torpedo missed!"); }
+
+ return quadrant.KlingonsFireOnEnterprise();
+ }
+
+ internal void ReplenishTorpedoes() => TorpedoCount = _tubeCount;
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ShieldControl.cs b/84_Super_Star_Trek/csharp/Systems/ShieldControl.cs
index de4f44d9..9d781b23 100644
--- a/84_Super_Star_Trek/csharp/Systems/ShieldControl.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ShieldControl.cs
@@ -1,59 +1,57 @@
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class ShieldControl : Subsystem
{
- internal class ShieldControl : Subsystem
+ private readonly Enterprise _enterprise;
+ private readonly IReadWrite _io;
+
+ internal ShieldControl(Enterprise enterprise, IReadWrite io)
+ : base("Shield Control", Command.SHE, io)
{
- private readonly Enterprise _enterprise;
- private readonly Output _output;
- private readonly Input _input;
-
- internal ShieldControl(Enterprise enterprise, Output output, Input input)
- : base("Shield Control", Command.SHE, output)
- {
- _enterprise = enterprise;
- _output = output;
- _input = input;
- }
-
- internal float ShieldEnergy { get; set; }
-
- protected override bool CanExecuteCommand() => IsOperational("{name} inoperable");
-
- protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
- {
- _output.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
- var requested = _input.GetNumber($"Number of units to shields");
-
- if (Validate(requested))
- {
- ShieldEnergy = requested;
- _output.Write(Strings.ShieldsSet, requested);
- }
- else
- {
- _output.WriteLine("");
- }
-
- return CommandResult.Ok;
- }
-
- private bool Validate(float requested)
- {
- if (requested > _enterprise.TotalEnergy)
- {
- _output.WriteLine("Shield Control reports, 'This is not the Federation Treasury.'");
- return false;
- }
-
- return requested >= 0 && requested != ShieldEnergy;
- }
-
- internal void AbsorbHit(int hitStrength) => ShieldEnergy -= hitStrength;
-
- internal void DropShields() => ShieldEnergy = 0;
+ _enterprise = enterprise;
+ _io = io;
}
+
+ internal float ShieldEnergy { get; set; }
+
+ protected override bool CanExecuteCommand() => IsOperational("{name} inoperable");
+
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ _io.WriteLine($"Energy available = {_enterprise.TotalEnergy}");
+ var requested = _io.ReadNumber($"Number of units to shields");
+
+ if (Validate(requested))
+ {
+ ShieldEnergy = requested;
+ _io.Write(Strings.ShieldsSet, requested);
+ }
+ else
+ {
+ _io.WriteLine("");
+ }
+
+ return CommandResult.Ok;
+ }
+
+ private bool Validate(float requested)
+ {
+ if (requested > _enterprise.TotalEnergy)
+ {
+ _io.WriteLine("Shield Control reports, 'This is not the Federation Treasury.'");
+ return false;
+ }
+
+ return requested >= 0 && requested != ShieldEnergy;
+ }
+
+ internal void AbsorbHit(int hitStrength) => ShieldEnergy -= hitStrength;
+
+ internal void DropShields() => ShieldEnergy = 0;
}
diff --git a/84_Super_Star_Trek/csharp/Systems/ShortRangeSensors.cs b/84_Super_Star_Trek/csharp/Systems/ShortRangeSensors.cs
index c37028cb..406af6b8 100644
--- a/84_Super_Star_Trek/csharp/Systems/ShortRangeSensors.cs
+++ b/84_Super_Star_Trek/csharp/Systems/ShortRangeSensors.cs
@@ -2,61 +2,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal class ShortRangeSensors : Subsystem
{
- internal class ShortRangeSensors : Subsystem
+ private readonly Enterprise _enterprise;
+ private readonly Galaxy _galaxy;
+ private readonly Game _game;
+ private readonly IReadWrite _io;
+
+ internal ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, IReadWrite io)
+ : base("Short Range Sensors", Command.SRS, io)
{
- private readonly Enterprise _enterprise;
- private readonly Galaxy _galaxy;
- private readonly Game _game;
- private readonly Output _output;
+ _enterprise = enterprise;
+ _galaxy = galaxy;
+ _game = game;
+ _io = io;
+ }
- internal ShortRangeSensors(Enterprise enterprise, Galaxy galaxy, Game game, Output output)
- : base("Short Range Sensors", Command.SRS, output)
+ protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ {
+ if (_enterprise.IsDocked)
{
- _enterprise = enterprise;
- _galaxy = galaxy;
- _game = game;
- _output = output;
+ _io.WriteLine(Strings.ShieldsDropped);
}
- protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
+ if (Condition < 0)
{
- if (_enterprise.IsDocked)
- {
- _output.WriteLine(Strings.ShieldsDropped);
- }
-
- if (Condition < 0)
- {
- _output.WriteLine(Strings.ShortRangeSensorsOut);
- }
-
- _output.WriteLine("---------------------------------");
- quadrant.GetDisplayLines()
- .Zip(GetStatusLines(), (sectors, status) => $" {sectors} {status}")
- .ToList()
- .ForEach(l => _output.WriteLine(l));
- _output.WriteLine("---------------------------------");
-
- return CommandResult.Ok;
+ _io.WriteLine(Strings.ShortRangeSensorsOut);
}
- internal IEnumerable GetStatusLines()
- {
- yield return $"Stardate {_game.Stardate}";
- yield return $"Condition {_enterprise.Condition}";
- yield return $"Quadrant {_enterprise.QuadrantCoordinates}";
- yield return $"Sector {_enterprise.SectorCoordinates}";
- yield return $"Photon torpedoes {_enterprise.PhotonTubes.TorpedoCount}";
- yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}";
- yield return $"Shields {(int)_enterprise.ShieldControl.ShieldEnergy}";
- yield return $"Klingons remaining {_galaxy.KlingonCount}";
- }
+ _io.WriteLine("---------------------------------");
+ quadrant.GetDisplayLines()
+ .Zip(GetStatusLines(), (sectors, status) => $" {sectors} {status}")
+ .ToList()
+ .ForEach(l => _io.WriteLine(l));
+ _io.WriteLine("---------------------------------");
+
+ return CommandResult.Ok;
+ }
+
+ internal IEnumerable GetStatusLines()
+ {
+ yield return $"Stardate {_game.Stardate}";
+ yield return $"Condition {_enterprise.Condition}";
+ yield return $"Quadrant {_enterprise.QuadrantCoordinates}";
+ yield return $"Sector {_enterprise.SectorCoordinates}";
+ yield return $"Photon torpedoes {_enterprise.PhotonTubes.TorpedoCount}";
+ yield return $"Total energy {Math.Ceiling(_enterprise.TotalEnergy)}";
+ yield return $"Shields {(int)_enterprise.ShieldControl.ShieldEnergy}";
+ 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 5c11e656..5a371103 100644
--- a/84_Super_Star_Trek/csharp/Systems/Subsystem.cs
+++ b/84_Super_Star_Trek/csharp/Systems/Subsystem.cs
@@ -1,68 +1,68 @@
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Space;
-namespace SuperStarTrek.Systems
+namespace SuperStarTrek.Systems;
+
+internal abstract class Subsystem
{
- internal abstract class Subsystem
+ private readonly IReadWrite _io;
+
+ protected Subsystem(string name, Command command, IReadWrite io)
{
- private readonly Output _output;
-
- protected Subsystem(string name, Command command, Output output)
- {
- Name = name;
- Command = command;
- Condition = 0;
- _output = output;
- }
-
- internal string Name { get; }
-
- internal float Condition { get; private set; }
-
- internal bool IsDamaged => Condition < 0;
-
- internal Command Command { get; }
-
- protected virtual bool CanExecuteCommand() => true;
-
- protected bool IsOperational(string notOperationalMessage)
- {
- if (IsDamaged)
- {
- _output.WriteLine(notOperationalMessage.Replace("{name}", Name));
- return false;
- }
-
- return true;
- }
-
- internal CommandResult ExecuteCommand(Quadrant quadrant)
- => CanExecuteCommand() ? ExecuteCommandCore(quadrant) : CommandResult.Ok;
-
- protected abstract CommandResult ExecuteCommandCore(Quadrant quadrant);
-
- internal virtual void Repair()
- {
- if (IsDamaged)
- {
- Condition = 0;
- }
- }
-
- internal virtual bool Repair(float repairWorkDone)
- {
- if (IsDamaged)
- {
- Condition += repairWorkDone;
- if (Condition > -0.1f && Condition < 0)
- {
- Condition = -0.1f;
- }
- }
-
- return !IsDamaged;
- }
-
- internal void TakeDamage(float damage) => Condition -= damage;
+ Name = name;
+ Command = command;
+ Condition = 0;
+ _io = io;
}
+
+ internal string Name { get; }
+
+ internal float Condition { get; private set; }
+
+ internal bool IsDamaged => Condition < 0;
+
+ internal Command Command { get; }
+
+ protected virtual bool CanExecuteCommand() => true;
+
+ protected bool IsOperational(string notOperationalMessage)
+ {
+ if (IsDamaged)
+ {
+ _io.WriteLine(notOperationalMessage.Replace("{name}", Name));
+ return false;
+ }
+
+ return true;
+ }
+
+ internal CommandResult ExecuteCommand(Quadrant quadrant)
+ => CanExecuteCommand() ? ExecuteCommandCore(quadrant) : CommandResult.Ok;
+
+ protected abstract CommandResult ExecuteCommandCore(Quadrant quadrant);
+
+ internal virtual void Repair()
+ {
+ if (IsDamaged)
+ {
+ Condition = 0;
+ }
+ }
+
+ internal virtual bool Repair(float repairWorkDone)
+ {
+ if (IsDamaged)
+ {
+ Condition += repairWorkDone;
+ if (Condition > -0.1f && Condition < 0)
+ {
+ Condition = -0.1f;
+ }
+ }
+
+ return !IsDamaged;
+ }
+
+ internal void TakeDamage(float damage) => Condition -= damage;
}
diff --git a/84_Super_Star_Trek/csharp/Systems/WarpEngines.cs b/84_Super_Star_Trek/csharp/Systems/WarpEngines.cs
index 096d0e43..a9651abf 100644
--- a/84_Super_Star_Trek/csharp/Systems/WarpEngines.cs
+++ b/84_Super_Star_Trek/csharp/Systems/WarpEngines.cs
@@ -1,4 +1,5 @@
using System;
+using Games.Common.IO;
using SuperStarTrek.Commands;
using SuperStarTrek.Objects;
using SuperStarTrek.Resources;
@@ -9,20 +10,18 @@ namespace SuperStarTrek.Systems
internal class WarpEngines : Subsystem
{
private readonly Enterprise _enterprise;
- private readonly Output _output;
- private readonly Input _input;
+ private readonly IReadWrite _io;
- internal WarpEngines(Enterprise enterprise, Output output, Input input)
- : base("Warp Engines", Command.NAV, output)
+ internal WarpEngines(Enterprise enterprise, IReadWrite io)
+ : base("Warp Engines", Command.NAV, io)
{
_enterprise = enterprise;
- _output = output;
- _input = input;
+ _io = io;
}
protected override CommandResult ExecuteCommandCore(Quadrant quadrant)
{
- if (_input.TryGetCourse("Course", " Lt. Sulu", out var course) &&
+ if (_io.TryReadCourse("Course", " Lt. Sulu", out var course) &&
TryGetWarpFactor(out var warpFactor) &&
TryGetDistanceToMove(warpFactor, out var distanceToMove))
{
@@ -51,12 +50,12 @@ namespace SuperStarTrek.Systems
private bool TryGetWarpFactor(out float warpFactor)
{
var maximumWarp = IsDamaged ? 0.2f : 8;
- if (_input.TryGetNumber("Warp Factor", 0, maximumWarp, out warpFactor))
+ if (_io.TryReadNumberInRange("Warp Factor", 0, maximumWarp, out warpFactor))
{
return warpFactor > 0;
}
- _output.WriteLine(
+ _io.WriteLine(
IsDamaged && warpFactor > maximumWarp
? "Warp engines are damaged. Maximum speed = warp 0.2"
: $" Chief Engineer Scott reports, 'The engines won't take warp {warpFactor} !'");
@@ -69,14 +68,14 @@ namespace SuperStarTrek.Systems
distanceToTravel = (int)Math.Round(warpFactor * 8, MidpointRounding.AwayFromZero);
if (distanceToTravel <= _enterprise.Energy) { return true; }
- _output.WriteLine("Engineering reports, 'Insufficient energy available")
- .WriteLine($" for maneuvering at warp {warpFactor} !'");
+ _io.WriteLine("Engineering reports, 'Insufficient energy available");
+ _io.WriteLine($" for maneuvering at warp {warpFactor} !'");
if (distanceToTravel <= _enterprise.TotalEnergy && !_enterprise.ShieldControl.IsDamaged)
{
- _output.Write($"Deflector control room acknowledges {_enterprise.ShieldControl.ShieldEnergy} ")
- .WriteLine("units of energy")
- .WriteLine(" presently deployed to shields.");
+ _io.Write($"Deflector control room acknowledges {_enterprise.ShieldControl.ShieldEnergy} ");
+ _io.WriteLine("units of energy");
+ _io.WriteLine(" presently deployed to shields.");
}
return false;