mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
99 lines
3.2 KiB
C#
99 lines
3.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
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
|
|
{
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
internal float DeltaX { get; }
|
|
|
|
internal float DeltaY { get; }
|
|
|
|
internal IEnumerable<Coordinates> GetSectorsFrom(Coordinates start)
|
|
{
|
|
(float x, float y) = start;
|
|
|
|
while(true)
|
|
{
|
|
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;
|
|
}
|
|
|
|
return newQuadrant switch
|
|
{
|
|
< 0 => (false, 0, 0),
|
|
> 7 => (false, 7, 7),
|
|
_ => (true, newQuadrant, newSector)
|
|
};
|
|
}
|
|
}
|
|
}
|