mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2026-01-09 11:46:24 -08:00
Removed spaces from top-level directory names.
Spaces tend to cause annoyances in a Unix-style shell environment. This change fixes that.
This commit is contained in:
231
84_Super_Star_Trek/csharp/Objects/Enterprise.cs
Normal file
231
84_Super_Star_Trek/csharp/Objects/Enterprise.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SuperStarTrek.Commands;
|
||||
using SuperStarTrek.Resources;
|
||||
using SuperStarTrek.Space;
|
||||
using SuperStarTrek.Systems;
|
||||
|
||||
namespace SuperStarTrek.Objects
|
||||
{
|
||||
internal class Enterprise
|
||||
{
|
||||
private readonly int _maxEnergy;
|
||||
private readonly Output _output;
|
||||
private readonly List<Subsystem> _systems;
|
||||
private readonly Dictionary<Command, Subsystem> _commandExecutors;
|
||||
private readonly Random _random;
|
||||
private readonly Input _input;
|
||||
private Quadrant _quadrant;
|
||||
|
||||
public Enterprise(int maxEnergy, Coordinates sector, Output output, Random random, Input input)
|
||||
{
|
||||
SectorCoordinates = sector;
|
||||
TotalEnergy = _maxEnergy = maxEnergy;
|
||||
|
||||
_systems = new List<Subsystem>();
|
||||
_commandExecutors = new Dictionary<Command, Subsystem>();
|
||||
_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<Subsystem> 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($" <Shields down to {ShieldControl.ShieldEnergy} units>");
|
||||
|
||||
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<string>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
43
84_Super_Star_Trek/csharp/Objects/Klingon.cs
Normal file
43
84_Super_Star_Trek/csharp/Objects/Klingon.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using SuperStarTrek.Commands;
|
||||
using SuperStarTrek.Space;
|
||||
|
||||
namespace SuperStarTrek.Objects
|
||||
{
|
||||
internal class Klingon
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
7
84_Super_Star_Trek/csharp/Objects/Star.cs
Normal file
7
84_Super_Star_Trek/csharp/Objects/Star.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace SuperStarTrek.Objects
|
||||
{
|
||||
internal class Star
|
||||
{
|
||||
public override string ToString() => " * ";
|
||||
}
|
||||
}
|
||||
45
84_Super_Star_Trek/csharp/Objects/Starbase.cs
Normal file
45
84_Super_Star_Trek/csharp/Objects/Starbase.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using SuperStarTrek.Resources;
|
||||
using SuperStarTrek.Space;
|
||||
|
||||
namespace SuperStarTrek.Objects
|
||||
{
|
||||
internal class Starbase
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user