mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 15:37:51 -08:00
Add Library-Computer
This commit is contained in:
@@ -3,6 +3,7 @@ using SuperStarTrek.Objects;
|
|||||||
using SuperStarTrek.Resources;
|
using SuperStarTrek.Resources;
|
||||||
using SuperStarTrek.Space;
|
using SuperStarTrek.Space;
|
||||||
using SuperStarTrek.Systems;
|
using SuperStarTrek.Systems;
|
||||||
|
using SuperStarTrek.Systems.ComputerFunctions;
|
||||||
using static System.StringComparison;
|
using static System.StringComparison;
|
||||||
|
|
||||||
namespace SuperStarTrek
|
namespace SuperStarTrek
|
||||||
@@ -16,7 +17,6 @@ namespace SuperStarTrek
|
|||||||
private int _finalStarDate;
|
private int _finalStarDate;
|
||||||
private float _currentStardate;
|
private float _currentStardate;
|
||||||
private Coordinates _currentQuadrant;
|
private Coordinates _currentQuadrant;
|
||||||
private Coordinates _currentSector;
|
|
||||||
private Galaxy _galaxy;
|
private Galaxy _galaxy;
|
||||||
private int _initialKlingonCount;
|
private int _initialKlingonCount;
|
||||||
private Enterprise _enterprise;
|
private Enterprise _enterprise;
|
||||||
@@ -28,6 +28,7 @@ namespace SuperStarTrek
|
|||||||
}
|
}
|
||||||
|
|
||||||
public float Stardate => _currentStardate;
|
public float Stardate => _currentStardate;
|
||||||
|
public float StardatesRemaining => _finalStarDate - _currentStardate;
|
||||||
|
|
||||||
public void DoIntroduction()
|
public void DoIntroduction()
|
||||||
{
|
{
|
||||||
@@ -74,7 +75,6 @@ namespace SuperStarTrek
|
|||||||
_finalStarDate = _initialStardate + random.GetInt(25, 35);
|
_finalStarDate = _initialStardate + random.GetInt(25, 35);
|
||||||
|
|
||||||
_currentQuadrant = random.GetCoordinate();
|
_currentQuadrant = random.GetCoordinate();
|
||||||
_currentSector = random.GetCoordinate();
|
|
||||||
|
|
||||||
_galaxy = new Galaxy();
|
_galaxy = new Galaxy();
|
||||||
_initialKlingonCount = _galaxy.KlingonCount;
|
_initialKlingonCount = _galaxy.KlingonCount;
|
||||||
@@ -85,7 +85,16 @@ namespace SuperStarTrek
|
|||||||
.Add(new LongRangeSensors(_galaxy, _output))
|
.Add(new LongRangeSensors(_galaxy, _output))
|
||||||
.Add(new PhotonTubes(10, _enterprise, _output, _input))
|
.Add(new PhotonTubes(10, _enterprise, _output, _input))
|
||||||
.Add(new ShieldControl(_enterprise, _output, _input))
|
.Add(new ShieldControl(_enterprise, _output, _input))
|
||||||
.Add(new DamageControl(_enterprise, _output));
|
.Add(new DamageControl(_enterprise, _output))
|
||||||
|
.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.Enterprise);
|
||||||
_output.Write(
|
_output.Write(
|
||||||
@@ -99,7 +108,7 @@ namespace SuperStarTrek
|
|||||||
|
|
||||||
_input.WaitForAnyKeyButEnter("when ready to accept command");
|
_input.WaitForAnyKeyButEnter("when ready to accept command");
|
||||||
|
|
||||||
var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy);
|
var quadrant = _galaxy[_currentQuadrant].BuildQuadrant(_enterprise, random, _galaxy, _input, _output);
|
||||||
_enterprise.Enter(quadrant, Strings.StartText);
|
_enterprise.Enter(quadrant, Strings.StartText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ namespace SuperStarTrek
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (float X, float Y) GetCoordinates(string prompt)
|
||||||
|
{
|
||||||
|
_output.Prompt($"{prompt} (X,Y)");
|
||||||
|
var responses = ReadNumbers(2);
|
||||||
|
return (responses[0], responses[1]);
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGetNumber(string prompt, float minValue, float maxValue, out float value)
|
public bool TryGetNumber(string prompt, float minValue, float maxValue, out float value)
|
||||||
{
|
{
|
||||||
value = GetNumber($"{prompt} ({minValue}-{maxValue})");
|
value = GetNumber($"{prompt} ({minValue}-{maxValue})");
|
||||||
@@ -90,6 +97,46 @@ namespace SuperStarTrek
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
public enum YesNoMode
|
public enum YesNoMode
|
||||||
{
|
{
|
||||||
TrueOnY,
|
TrueOnY,
|
||||||
|
|||||||
@@ -6,25 +6,27 @@ namespace SuperStarTrek.Objects
|
|||||||
internal class Klingon
|
internal class Klingon
|
||||||
{
|
{
|
||||||
private float _energy;
|
private float _energy;
|
||||||
private Coordinates _sector;
|
|
||||||
private readonly Random _random;
|
private readonly Random _random;
|
||||||
|
|
||||||
public Klingon(Coordinates sector, Random random)
|
public Klingon(Coordinates sector, Random random)
|
||||||
{
|
{
|
||||||
_sector = sector;
|
Sector = sector;
|
||||||
_random = random;
|
_random = random;
|
||||||
_energy = _random.GetFloat(100, 300);
|
_energy = _random.GetFloat(100, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Coordinates Sector { get; private set; }
|
||||||
|
|
||||||
public override string ToString() => "+K+";
|
public override string ToString() => "+K+";
|
||||||
|
|
||||||
public CommandResult FireOn(Enterprise enterprise)
|
public CommandResult FireOn(Enterprise enterprise)
|
||||||
{
|
{
|
||||||
var attackStrength = _random.GetFloat();
|
var attackStrength = _random.GetFloat();
|
||||||
var hitStrength = (int)(_energy * (2 + attackStrength) / _sector.GetDistanceTo(enterprise.Sector));
|
var (_, distanceToEnterprise) = Sector.GetDirectionAndDistanceTo(enterprise.Sector);
|
||||||
|
var hitStrength = (int)(_energy * (2 + attackStrength) / distanceToEnterprise);
|
||||||
_energy /= 3 + attackStrength;
|
_energy /= 3 + attackStrength;
|
||||||
|
|
||||||
return enterprise.TakeHit(_sector, hitStrength);
|
return enterprise.TakeHit(Sector, hitStrength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SuperStarTrek.Resources;
|
using SuperStarTrek.Resources;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
namespace SuperStarTrek.Objects
|
namespace SuperStarTrek.Objects
|
||||||
{
|
{
|
||||||
@@ -8,13 +9,15 @@ namespace SuperStarTrek.Objects
|
|||||||
private readonly Output _output;
|
private readonly Output _output;
|
||||||
private readonly float _repairDelay;
|
private readonly float _repairDelay;
|
||||||
|
|
||||||
public Starbase(Random random, Input input, Output output)
|
public Starbase(Coordinates sector, Random random, Input input, Output output)
|
||||||
{
|
{
|
||||||
|
Sector = sector;
|
||||||
_repairDelay = random.GetFloat() * 0.5f;
|
_repairDelay = random.GetFloat() * 0.5f;
|
||||||
_input = input;
|
_input = input;
|
||||||
_output = output;
|
_output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal Coordinates Sector { get; }
|
||||||
public override string ToString() => ">!<";
|
public override string ToString() => ">!<";
|
||||||
|
|
||||||
internal bool TryRepair(Enterprise enterprise, out float repairTime)
|
internal bool TryRepair(Enterprise enterprise, out float repairTime)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace SuperStarTrek
|
|||||||
{
|
{
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
|
var foo = Utils.DirectionAndDistance.From(1,1).To(4,5);
|
||||||
var game = new Game();
|
var game = new Game();
|
||||||
|
|
||||||
game.DoIntroduction();
|
game.DoIntroduction();
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
Functions available from Library-Computer:
|
||||||
|
0 = Cumulative galactic record
|
||||||
|
1 = Status report
|
||||||
|
2 = Photon torpedo data
|
||||||
|
3 = Starbase nav data
|
||||||
|
4 = Direction/distance calculator
|
||||||
|
5 = Galaxy 'region name' map
|
||||||
|
|
||||||
2
84 Super Star Trek/csharp/Resources/NoEnemyShips.txt
Normal file
2
84 Super Star Trek/csharp/Resources/NoEnemyShips.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Science Officer Spock reports, 'Sensors show no enemy ships
|
||||||
|
in this quadrant'
|
||||||
1
84 Super Star Trek/csharp/Resources/NoStarbase.txt
Normal file
1
84 Super Star Trek/csharp/Resources/NoStarbase.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Mr. Spock reports, 'Sensors show no starbases in this quadrant.'
|
||||||
@@ -7,6 +7,7 @@ namespace SuperStarTrek.Resources
|
|||||||
internal static class Strings
|
internal static class Strings
|
||||||
{
|
{
|
||||||
public static string CombatArea => GetResource();
|
public static string CombatArea => GetResource();
|
||||||
|
public static string ComputerFunctions => GetResource();
|
||||||
public static string Congratulations => GetResource();
|
public static string Congratulations => GetResource();
|
||||||
public static string CourtMartial => GetResource();
|
public static string CourtMartial => GetResource();
|
||||||
public static string Destroyed => GetResource();
|
public static string Destroyed => GetResource();
|
||||||
@@ -14,6 +15,8 @@ namespace SuperStarTrek.Resources
|
|||||||
public static string Enterprise => GetResource();
|
public static string Enterprise => GetResource();
|
||||||
public static string Instructions => GetResource();
|
public static string Instructions => GetResource();
|
||||||
public static string LowShields => GetResource();
|
public static string LowShields => GetResource();
|
||||||
|
public static string NoEnemyShips => GetResource();
|
||||||
|
public static string NoStarbase => GetResource();
|
||||||
public static string Orders => GetResource();
|
public static string Orders => GetResource();
|
||||||
public static string Protected => GetResource();
|
public static string Protected => GetResource();
|
||||||
public static string RegionNames => GetResource();
|
public static string RegionNames => GetResource();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using SuperStarTrek.Utils;
|
||||||
|
|
||||||
namespace SuperStarTrek.Space
|
namespace SuperStarTrek.Space
|
||||||
{
|
{
|
||||||
@@ -10,12 +11,15 @@ namespace SuperStarTrek.Space
|
|||||||
{
|
{
|
||||||
X = Validated(x, nameof(x));
|
X = Validated(x, nameof(x));
|
||||||
Y = Validated(y, nameof(y));
|
Y = Validated(y, nameof(y));
|
||||||
|
|
||||||
|
RegionIndex = (X << 1) + (Y >> 2);
|
||||||
|
SubRegionIndex = Y % 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int X { get; }
|
public int X { get; }
|
||||||
public int Y { get; }
|
public int Y { get; }
|
||||||
public int RegionIndex => (X << 1) + (Y >> 2);
|
public int RegionIndex { get; }
|
||||||
public int SubRegionIndex => Y % 4;
|
public int SubRegionIndex { get; }
|
||||||
|
|
||||||
private int Validated(int value, string argumentName)
|
private int Validated(int value, string argumentName)
|
||||||
{
|
{
|
||||||
@@ -51,7 +55,7 @@ namespace SuperStarTrek.Space
|
|||||||
int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
|
int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal float GetDistanceTo(Coordinates destination) =>
|
internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) =>
|
||||||
(float)Math.Sqrt(Math.Pow(X - destination.X, 2) + Math.Pow(Y - destination.Y, 2));
|
DirectionAndDistance.From(this).To(destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace SuperStarTrek.Space
|
|||||||
|
|
||||||
public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount);
|
public int KlingonCount => _quadrants.SelectMany(q => q).Sum(q => q.KlingonCount);
|
||||||
public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
|
public int StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
|
||||||
|
public IEnumerable<IEnumerable<QuadrantInfo>> Quadrants => _quadrants;
|
||||||
|
|
||||||
private static string GetQuadrantName(Coordinates coordinates) =>
|
private static string GetQuadrantName(Coordinates coordinates) =>
|
||||||
$"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}";
|
$"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}";
|
||||||
|
|||||||
@@ -13,10 +13,15 @@ namespace SuperStarTrek.Space
|
|||||||
private readonly Random _random;
|
private readonly Random _random;
|
||||||
private readonly Dictionary<Coordinates, object> _sectors;
|
private readonly Dictionary<Coordinates, object> _sectors;
|
||||||
private readonly Enterprise _enterprise;
|
private readonly Enterprise _enterprise;
|
||||||
private readonly Coordinates _starbaseSector;
|
|
||||||
private readonly Galaxy _galaxy;
|
private readonly Galaxy _galaxy;
|
||||||
|
|
||||||
public Quadrant(QuadrantInfo info, Enterprise enterprise, Random random, Galaxy galaxy)
|
public Quadrant(
|
||||||
|
QuadrantInfo info,
|
||||||
|
Enterprise enterprise,
|
||||||
|
Random random,
|
||||||
|
Galaxy galaxy,
|
||||||
|
Input input,
|
||||||
|
Output output)
|
||||||
{
|
{
|
||||||
_info = info;
|
_info = info;
|
||||||
_random = random;
|
_random = random;
|
||||||
@@ -26,30 +31,30 @@ namespace SuperStarTrek.Space
|
|||||||
PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
|
PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
|
||||||
if (_info.HasStarbase)
|
if (_info.HasStarbase)
|
||||||
{
|
{
|
||||||
_starbaseSector = PositionObject(_ => new Starbase(_random, new Input(new Output()), new Output()));
|
Starbase = PositionObject(sector => new Starbase(sector, _random, input, output));
|
||||||
}
|
}
|
||||||
PositionObject(_ => new Star(), _info.StarCount);
|
PositionObject(_ => new Star(), _info.StarCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object this[Coordinates coordinates] => _sectors.GetValueOrDefault(coordinates);
|
|
||||||
public Coordinates Coordinates => _info.Coordinates;
|
public Coordinates Coordinates => _info.Coordinates;
|
||||||
public bool HasKlingons => _info.KlingonCount > 0;
|
public bool HasKlingons => _info.KlingonCount > 0;
|
||||||
|
public int KlingonCount => _info.KlingonCount;
|
||||||
public bool HasStarbase => _info.HasStarbase;
|
public bool HasStarbase => _info.HasStarbase;
|
||||||
public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null;
|
public Starbase Starbase { get; }
|
||||||
public bool EnterpriseIsNextToStarbase =>
|
public bool EnterpriseIsNextToStarbase =>
|
||||||
_info.HasStarbase &&
|
_info.HasStarbase &&
|
||||||
Math.Abs(_enterprise.Sector.X - _starbaseSector.X) <= 1 &&
|
Math.Abs(_enterprise.Sector.X - Starbase.Sector.X) <= 1 &&
|
||||||
Math.Abs(_enterprise.Sector.Y - _starbaseSector.Y) <= 1;
|
Math.Abs(_enterprise.Sector.Y - Starbase.Sector.Y) <= 1;
|
||||||
|
|
||||||
private IEnumerable<Klingon> Klingons => _sectors.Values.OfType<Klingon>();
|
internal IEnumerable<Klingon> Klingons => _sectors.Values.OfType<Klingon>();
|
||||||
|
|
||||||
public override string ToString() => _info.Name;
|
public override string ToString() => _info.Name;
|
||||||
|
|
||||||
private Coordinates PositionObject(Func<Coordinates, object> objectFactory)
|
private T PositionObject<T>(Func<Coordinates, T> objectFactory)
|
||||||
{
|
{
|
||||||
var sector = GetRandomEmptySector();
|
var sector = GetRandomEmptySector();
|
||||||
_sectors[sector] = objectFactory.Invoke(sector);
|
_sectors[sector] = objectFactory.Invoke(sector);
|
||||||
return sector;
|
return (T)_sectors[sector];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PositionObject(Func<Coordinates, object> objectFactory, int count)
|
private void PositionObject(Func<Coordinates, object> objectFactory, int count)
|
||||||
|
|||||||
@@ -41,8 +41,11 @@ namespace SuperStarTrek.Space
|
|||||||
|
|
||||||
internal void AddStarbase() => HasStarbase = true;
|
internal void AddStarbase() => HasStarbase = true;
|
||||||
|
|
||||||
internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy) =>
|
internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy, Input input, Output output)
|
||||||
new(this, enterprise, random, galaxy);
|
{
|
||||||
|
_isKnown = true;
|
||||||
|
return new(this, enterprise, random, galaxy, input, output);
|
||||||
|
}
|
||||||
|
|
||||||
internal string Scan()
|
internal string Scan()
|
||||||
{
|
{
|
||||||
|
|||||||
7
84 Super Star Trek/csharp/StringExtensions.cs
Normal file
7
84 Super Star Trek/csharp/StringExtensions.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace SuperStarTrek
|
||||||
|
{
|
||||||
|
internal static class StringExtensions
|
||||||
|
{
|
||||||
|
internal static string Pluralize(this string singular, int quantity) => singular + (quantity > 1 ? "s" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal abstract class ComputerFunction
|
||||||
|
{
|
||||||
|
protected ComputerFunction(string description, Output output)
|
||||||
|
{
|
||||||
|
Description = description;
|
||||||
|
Output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string Description { get; }
|
||||||
|
protected Output Output { get; }
|
||||||
|
|
||||||
|
internal abstract void Execute(Quadrant quadrant);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal class CumulativeGalacticRecord : GalacticReport
|
||||||
|
{
|
||||||
|
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<string> GetRowData() =>
|
||||||
|
Galaxy.Quadrants.Select(row => " " + string.Join(" ", row));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using SuperStarTrek.Objects;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal class DirectionDistanceCalculator : NavigationCalculator
|
||||||
|
{
|
||||||
|
private readonly Enterprise _enterprise;
|
||||||
|
private readonly Input _input;
|
||||||
|
|
||||||
|
public DirectionDistanceCalculator(Enterprise enterprise, Output output, Input input)
|
||||||
|
: base("Starbase nav data", output)
|
||||||
|
{
|
||||||
|
_enterprise = enterprise;
|
||||||
|
_input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Execute(Quadrant quadrant)
|
||||||
|
{
|
||||||
|
Output.WriteLine("Direction/distance calculator:")
|
||||||
|
.WriteLine($"You are at quadrant {_enterprise.Quadrant} sector {_enterprise.Sector}")
|
||||||
|
.WriteLine("Please enter");
|
||||||
|
|
||||||
|
WriteDirectionAndDistance(
|
||||||
|
_input.GetCoordinates(" Initial coordinates"),
|
||||||
|
_input.GetCoordinates(" Final coordinates"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal abstract class GalacticReport : ComputerFunction
|
||||||
|
{
|
||||||
|
public 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<string> 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(" ----- ----- ----- ----- ----- ----- ----- -----");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using SuperStarTrek.Resources;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal class GalaxyRegionMap : GalacticReport
|
||||||
|
{
|
||||||
|
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<string> GetRowData() =>
|
||||||
|
Strings.RegionNames.Split('\n').Select(n => n.TrimEnd('\r'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using SuperStarTrek.Space;
|
||||||
|
using SuperStarTrek.Utils;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal abstract class NavigationCalculator : ComputerFunction
|
||||||
|
{
|
||||||
|
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((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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using SuperStarTrek.Objects;
|
||||||
|
using SuperStarTrek.Resources;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal class StarbaseDataCalculator : NavigationCalculator
|
||||||
|
{
|
||||||
|
private readonly Enterprise _enterprise;
|
||||||
|
|
||||||
|
public StarbaseDataCalculator(Enterprise enterprise, Output output)
|
||||||
|
: base("Starbase nav data", output)
|
||||||
|
{
|
||||||
|
_enterprise = enterprise;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Execute(Quadrant quadrant)
|
||||||
|
{
|
||||||
|
if (!quadrant.HasStarbase)
|
||||||
|
{
|
||||||
|
Output.WriteLine(Strings.NoStarbase);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output.WriteLine("From Enterprise to Starbase:");
|
||||||
|
|
||||||
|
WriteDirectionAndDistance(_enterprise.Sector, quadrant.Starbase.Sector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using SuperStarTrek.Commands;
|
||||||
|
using SuperStarTrek.Objects;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal class StatusReport : ComputerFunction
|
||||||
|
{
|
||||||
|
private readonly Game _game;
|
||||||
|
private readonly Galaxy _galaxy;
|
||||||
|
private readonly Enterprise _enterprise;
|
||||||
|
|
||||||
|
public StatusReport(Game game, Galaxy galaxy, Enterprise enterprise, Output output)
|
||||||
|
: base("Status report", output)
|
||||||
|
{
|
||||||
|
_game = game;
|
||||||
|
_galaxy = galaxy;
|
||||||
|
_enterprise = enterprise;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using SuperStarTrek.Objects;
|
||||||
|
using SuperStarTrek.Resources;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems.ComputerFunctions
|
||||||
|
{
|
||||||
|
internal class TorpedoDataCalculator : NavigationCalculator
|
||||||
|
{
|
||||||
|
private readonly Enterprise _enterprise;
|
||||||
|
|
||||||
|
public TorpedoDataCalculator(Enterprise enterprise, Output output)
|
||||||
|
: base("Photon torpedo data", output)
|
||||||
|
{
|
||||||
|
_enterprise = enterprise;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Execute(Quadrant quadrant)
|
||||||
|
{
|
||||||
|
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.Sector, klingon.Sector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ namespace SuperStarTrek.Systems
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_output.NextLine();
|
||||||
WriteDamageReport();
|
WriteDamageReport();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ namespace SuperStarTrek.Systems
|
|||||||
|
|
||||||
public void WriteDamageReport()
|
public void WriteDamageReport()
|
||||||
{
|
{
|
||||||
_output.NextLine().NextLine().WriteLine("Device State of Repair");
|
_output.NextLine().WriteLine("Device State of Repair");
|
||||||
foreach (var system in _enterprise.Systems)
|
foreach (var system in _enterprise.Systems)
|
||||||
{
|
{
|
||||||
_output.Write(system.Name.PadRight(25))
|
_output.Write(system.Name.PadRight(25))
|
||||||
|
|||||||
47
84 Super Star Trek/csharp/Systems/LibraryComputer.cs
Normal file
47
84 Super Star Trek/csharp/Systems/LibraryComputer.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using SuperStarTrek.Commands;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
using SuperStarTrek.Systems.ComputerFunctions;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Systems
|
||||||
|
{
|
||||||
|
internal class LibraryComputer : Subsystem
|
||||||
|
{
|
||||||
|
private readonly Output _output;
|
||||||
|
private readonly Input _input;
|
||||||
|
private readonly ComputerFunction[] _functions;
|
||||||
|
|
||||||
|
public LibraryComputer(Output output, Input input, params ComputerFunction[] functions)
|
||||||
|
: base("Library-Computer", Command.COM, output)
|
||||||
|
{
|
||||||
|
_output = output;
|
||||||
|
_input = input;
|
||||||
|
_functions = functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs
Normal file
65
84 Super Star Trek/csharp/Utils/DirectionAndDistance.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using SuperStarTrek.Space;
|
||||||
|
|
||||||
|
namespace SuperStarTrek.Utils
|
||||||
|
{
|
||||||
|
internal class DirectionAndDistance
|
||||||
|
{
|
||||||
|
private readonly float _fromX;
|
||||||
|
private readonly float _fromY;
|
||||||
|
|
||||||
|
private DirectionAndDistance(float fromX, float fromY)
|
||||||
|
{
|
||||||
|
_fromX = fromX;
|
||||||
|
_fromY = fromY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DirectionAndDistance From(Coordinates coordinates) => From(coordinates.X, coordinates.Y);
|
||||||
|
|
||||||
|
public static DirectionAndDistance From(float x, float y) => new DirectionAndDistance(x, y);
|
||||||
|
|
||||||
|
public (float Direction, float Distance) To(Coordinates coordinates) => To(coordinates.X, coordinates.Y);
|
||||||
|
|
||||||
|
public (float Direction, float Distance) To(float x, float y)
|
||||||
|
{
|
||||||
|
var deltaX = x - _fromX;
|
||||||
|
var deltaY = y - _fromY;
|
||||||
|
|
||||||
|
return (GetDirection(deltaX, deltaY), GetDistance(deltaX, deltaY));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The algorithm here is mathematically equivalent to the following code in the original,
|
||||||
|
// where X is deltaY and A is deltaX
|
||||||
|
// 8220 X=X-A:A=C1-W1:IFX<0THEN8350
|
||||||
|
// 8250 IFA<0THEN8410
|
||||||
|
// 8260 IFX>0THEN8280
|
||||||
|
// 8270 IFA=0THENC1=5:GOTO8290
|
||||||
|
// 8280 C1=1
|
||||||
|
// 8290 IFABS(A)<=ABS(X)THEN8330
|
||||||
|
// 8310 PRINT"DIRECTION =";C1+(((ABS(A)-ABS(X))+ABS(A))/ABS(A)):GOTO8460
|
||||||
|
// 8330 PRINT"DIRECTION =";C1+(ABS(A)/ABS(X)):GOTO8460
|
||||||
|
// 8350 IFA>0THENC1=3:GOTO8420
|
||||||
|
// 8360 IFX<>0THENC1=5:GOTO8290
|
||||||
|
// 8410 C1=7
|
||||||
|
// 8420 IFABS(A)>=ABS(X)THEN8450
|
||||||
|
// 8430 PRINT"DIRECTION =";C1+(((ABS(X)-ABS(A))+ABS(X))/ABS(X)):GOTO8460
|
||||||
|
// 8450 PRINT"DIRECTION =";C1+(ABS(X)/ABS(A))
|
||||||
|
// 8460 PRINT"DISTANCE =";SQR(X^2+A^2):IFH8=1THEN1990
|
||||||
|
private float GetDirection(float deltaX, float deltaY)
|
||||||
|
{
|
||||||
|
var deltaXDominant = Math.Abs(deltaX) > Math.Abs(deltaY);
|
||||||
|
var fractionalPart = deltaXDominant ? deltaY / deltaX : -deltaX / deltaY;
|
||||||
|
var nearestCardinal = deltaXDominant switch
|
||||||
|
{
|
||||||
|
true => deltaX > 0 ? 7 : 3,
|
||||||
|
false => deltaY > 0 ? 1 : 5
|
||||||
|
};
|
||||||
|
|
||||||
|
var direction = nearestCardinal + fractionalPart;
|
||||||
|
return direction < 1 ? direction + 8 : direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetDistance(float deltaX, float deltaY) =>
|
||||||
|
(float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user