Files
Christopher Wiebe b451f83174 Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback
anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md).
All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:40:51 -07:00

69 lines
2.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace Theriapolis.Core.Util;
/// <summary>
/// Direction encoding for tile-level features (rivers, rail, roads).
/// Directions are stored as byte values 07, matching the 8 compass points.
/// 255 = "no direction" / unset.
/// </summary>
public static class Dir
{
// Direction constants (0-based, CCW from North)
public const byte None = 255;
public const byte N = 0; // (dx= 0, dy=-1)
public const byte NE = 1; // (dx= 1, dy=-1)
public const byte E = 2; // (dx= 1, dy= 0)
public const byte SE = 3; // (dx= 1, dy= 1)
public const byte S = 4; // (dx= 0, dy= 1)
public const byte SW = 5; // (dx=-1, dy= 1)
public const byte W = 6; // (dx=-1, dy= 0)
public const byte NW = 7; // (dx=-1, dy=-1)
private static readonly (int dx, int dy)[] _deltas =
{
( 0,-1), ( 1,-1), ( 1, 0), ( 1, 1),
( 0, 1), (-1, 1), (-1, 0), (-1,-1),
};
/// <summary>Convert a (dx, dy) delta to a direction byte. Both values must be in {-1,0,1}.</summary>
public static byte FromDelta(int dx, int dy)
{
for (byte i = 0; i < 8; i++)
if (_deltas[i].dx == dx && _deltas[i].dy == dy)
return i;
return None;
}
public static (int dx, int dy) ToDelta(byte dir)
{
if (dir == None) return (0, 0);
return _deltas[dir & 7];
}
/// <summary>
/// Two directions are parallel if their angular difference is ≤ 45° (including opposite directions).
/// </summary>
public static bool IsParallel(byte a, byte b)
{
if (a == None || b == None) return false;
int diff = Math.Abs((int)(a & 7) - (int)(b & 7));
diff = Math.Min(diff, 8 - diff);
// diff 0 = same; diff 1 = 45°; diff 4 = 180° (opposite still parallel)
return diff <= 1 || diff >= 3; // ≤45° or ≥135° (anti-parallel)
}
/// <summary>
/// Two directions are perpendicular if their angular difference is in [60°, 120°].
/// Using discrete 45° steps: diff 2 = 90°.
/// </summary>
public static bool IsPerpendicular(byte a, byte b)
{
if (a == None || b == None) return false;
int diff = Math.Abs((int)(a & 7) - (int)(b & 7));
diff = Math.Min(diff, 8 - diff);
return diff == 2;
}
/// <summary>Opposite direction.</summary>
public static byte Opposite(byte d) => d == None ? None : (byte)((d + 4) & 7);
}