mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
Add Library-Computer
This commit is contained in:
@@ -3,6 +3,7 @@ using SuperStarTrek.Objects;
|
||||
using SuperStarTrek.Resources;
|
||||
using SuperStarTrek.Space;
|
||||
using SuperStarTrek.Systems;
|
||||
using SuperStarTrek.Systems.ComputerFunctions;
|
||||
using static System.StringComparison;
|
||||
|
||||
namespace SuperStarTrek
|
||||
@@ -16,7 +17,6 @@ namespace SuperStarTrek
|
||||
private int _finalStarDate;
|
||||
private float _currentStardate;
|
||||
private Coordinates _currentQuadrant;
|
||||
private Coordinates _currentSector;
|
||||
private Galaxy _galaxy;
|
||||
private int _initialKlingonCount;
|
||||
private Enterprise _enterprise;
|
||||
@@ -28,6 +28,7 @@ namespace SuperStarTrek
|
||||
}
|
||||
|
||||
public float Stardate => _currentStardate;
|
||||
public float StardatesRemaining => _finalStarDate - _currentStardate;
|
||||
|
||||
public void DoIntroduction()
|
||||
{
|
||||
@@ -74,7 +75,6 @@ namespace SuperStarTrek
|
||||
_finalStarDate = _initialStardate + random.GetInt(25, 35);
|
||||
|
||||
_currentQuadrant = random.GetCoordinate();
|
||||
_currentSector = random.GetCoordinate();
|
||||
|
||||
_galaxy = new Galaxy();
|
||||
_initialKlingonCount = _galaxy.KlingonCount;
|
||||
@@ -85,7 +85,16 @@ namespace SuperStarTrek
|
||||
.Add(new LongRangeSensors(_galaxy, _output))
|
||||
.Add(new PhotonTubes(10, _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(
|
||||
@@ -99,7 +108,7 @@ namespace SuperStarTrek
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
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
|
||||
{
|
||||
TrueOnY,
|
||||
|
||||
@@ -6,25 +6,27 @@ namespace SuperStarTrek.Objects
|
||||
internal class Klingon
|
||||
{
|
||||
private float _energy;
|
||||
private Coordinates _sector;
|
||||
private readonly Random _random;
|
||||
|
||||
public Klingon(Coordinates sector, Random random)
|
||||
{
|
||||
_sector = sector;
|
||||
Sector = sector;
|
||||
_random = random;
|
||||
_energy = _random.GetFloat(100, 300);
|
||||
}
|
||||
|
||||
public Coordinates Sector { get; private set; }
|
||||
|
||||
public override string ToString() => "+K+";
|
||||
|
||||
public CommandResult FireOn(Enterprise enterprise)
|
||||
{
|
||||
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;
|
||||
|
||||
return enterprise.TakeHit(_sector, hitStrength);
|
||||
return enterprise.TakeHit(Sector, hitStrength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SuperStarTrek.Resources;
|
||||
using SuperStarTrek.Space;
|
||||
|
||||
namespace SuperStarTrek.Objects
|
||||
{
|
||||
@@ -8,13 +9,15 @@ namespace SuperStarTrek.Objects
|
||||
private readonly Output _output;
|
||||
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;
|
||||
_input = input;
|
||||
_output = output;
|
||||
}
|
||||
|
||||
internal Coordinates Sector { get; }
|
||||
public override string ToString() => ">!<";
|
||||
|
||||
internal bool TryRepair(Enterprise enterprise, out float repairTime)
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace SuperStarTrek
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var foo = Utils.DirectionAndDistance.From(1,1).To(4,5);
|
||||
var game = new Game();
|
||||
|
||||
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.'
|
||||
@@ -1,8 +1,8 @@
|
||||
Antares Sirius
|
||||
Rigel Deneb
|
||||
Procyon Capella
|
||||
Vega Betelgeuse
|
||||
Canopus Aldebaran
|
||||
Altair Regulus
|
||||
Sagittarius Arcturus
|
||||
Pollux Spica
|
||||
Antares Sirius
|
||||
Rigel Deneb
|
||||
Procyon Capella
|
||||
Vega Betelgeuse
|
||||
Canopus Aldebaran
|
||||
Altair Regulus
|
||||
Sagittarius Arcturus
|
||||
Pollux Spica
|
||||
@@ -7,6 +7,7 @@ namespace SuperStarTrek.Resources
|
||||
internal static class Strings
|
||||
{
|
||||
public static string CombatArea => GetResource();
|
||||
public static string ComputerFunctions => GetResource();
|
||||
public static string Congratulations => GetResource();
|
||||
public static string CourtMartial => GetResource();
|
||||
public static string Destroyed => GetResource();
|
||||
@@ -14,6 +15,8 @@ namespace SuperStarTrek.Resources
|
||||
public static string Enterprise => GetResource();
|
||||
public static string Instructions => GetResource();
|
||||
public static string LowShields => GetResource();
|
||||
public static string NoEnemyShips => GetResource();
|
||||
public static string NoStarbase => GetResource();
|
||||
public static string Orders => GetResource();
|
||||
public static string Protected => GetResource();
|
||||
public static string RegionNames => GetResource();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using SuperStarTrek.Utils;
|
||||
|
||||
namespace SuperStarTrek.Space
|
||||
{
|
||||
@@ -10,12 +11,15 @@ namespace SuperStarTrek.Space
|
||||
{
|
||||
X = Validated(x, nameof(x));
|
||||
Y = Validated(y, nameof(y));
|
||||
|
||||
RegionIndex = (X << 1) + (Y >> 2);
|
||||
SubRegionIndex = Y % 4;
|
||||
}
|
||||
|
||||
public int X { get; }
|
||||
public int Y { get; }
|
||||
public int RegionIndex => (X << 1) + (Y >> 2);
|
||||
public int SubRegionIndex => Y % 4;
|
||||
public int RegionIndex { get; }
|
||||
public int SubRegionIndex { get; }
|
||||
|
||||
private int Validated(int value, string argumentName)
|
||||
{
|
||||
@@ -51,7 +55,7 @@ namespace SuperStarTrek.Space
|
||||
int Round(float value) => (int)Math.Round(value, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
internal float GetDistanceTo(Coordinates destination) =>
|
||||
(float)Math.Sqrt(Math.Pow(X - destination.X, 2) + Math.Pow(Y - destination.Y, 2));
|
||||
internal (float Direction, float Distance) GetDirectionAndDistanceTo(Coordinates destination) =>
|
||||
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 StarbaseCount => _quadrants.SelectMany(q => q).Count(q => q.HasStarbase);
|
||||
public IEnumerable<IEnumerable<QuadrantInfo>> Quadrants => _quadrants;
|
||||
|
||||
private static string GetQuadrantName(Coordinates coordinates) =>
|
||||
$"{_regionNames[coordinates.RegionIndex]} {_subRegionIdentifiers[coordinates.SubRegionIndex]}";
|
||||
|
||||
@@ -13,10 +13,15 @@ namespace SuperStarTrek.Space
|
||||
private readonly Random _random;
|
||||
private readonly Dictionary<Coordinates, object> _sectors;
|
||||
private readonly Enterprise _enterprise;
|
||||
private readonly Coordinates _starbaseSector;
|
||||
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;
|
||||
_random = random;
|
||||
@@ -26,30 +31,30 @@ namespace SuperStarTrek.Space
|
||||
PositionObject(sector => new Klingon(sector, _random), _info.KlingonCount);
|
||||
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);
|
||||
}
|
||||
|
||||
public object this[Coordinates coordinates] => _sectors.GetValueOrDefault(coordinates);
|
||||
public Coordinates Coordinates => _info.Coordinates;
|
||||
public bool HasKlingons => _info.KlingonCount > 0;
|
||||
public int KlingonCount => _info.KlingonCount;
|
||||
public bool HasStarbase => _info.HasStarbase;
|
||||
public Starbase Starbase => HasStarbase ? (Starbase)_sectors[_starbaseSector] : null;
|
||||
public Starbase Starbase { get; }
|
||||
public bool EnterpriseIsNextToStarbase =>
|
||||
_info.HasStarbase &&
|
||||
Math.Abs(_enterprise.Sector.X - _starbaseSector.X) <= 1 &&
|
||||
Math.Abs(_enterprise.Sector.Y - _starbaseSector.Y) <= 1;
|
||||
Math.Abs(_enterprise.Sector.X - Starbase.Sector.X) <= 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;
|
||||
|
||||
private Coordinates PositionObject(Func<Coordinates, object> objectFactory)
|
||||
private T PositionObject<T>(Func<Coordinates, T> objectFactory)
|
||||
{
|
||||
var sector = GetRandomEmptySector();
|
||||
_sectors[sector] = objectFactory.Invoke(sector);
|
||||
return sector;
|
||||
return (T)_sectors[sector];
|
||||
}
|
||||
|
||||
private void PositionObject(Func<Coordinates, object> objectFactory, int count)
|
||||
|
||||
@@ -41,8 +41,11 @@ namespace SuperStarTrek.Space
|
||||
|
||||
internal void AddStarbase() => HasStarbase = true;
|
||||
|
||||
internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy) =>
|
||||
new(this, enterprise, random, galaxy);
|
||||
internal Quadrant BuildQuadrant(Enterprise enterprise, Random random, Galaxy galaxy, Input input, Output output)
|
||||
{
|
||||
_isKnown = true;
|
||||
return new(this, enterprise, random, galaxy, input, output);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
_output.NextLine();
|
||||
WriteDamageReport();
|
||||
}
|
||||
|
||||
@@ -41,7 +42,7 @@ namespace SuperStarTrek.Systems
|
||||
|
||||
public void WriteDamageReport()
|
||||
{
|
||||
_output.NextLine().NextLine().WriteLine("Device State of Repair");
|
||||
_output.NextLine().WriteLine("Device State of Repair");
|
||||
foreach (var system in _enterprise.Systems)
|
||||
{
|
||||
_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