Skip to content

Commit

Permalink
Merge pull request #138 from CyberiaResurrection/HexEquality
Browse files Browse the repository at this point in the history
Add __eq__ to Hex, & type-hint it
  • Loading branch information
CyberiaResurrection authored Jan 18, 2025
2 parents 4e33ed1 + b8f1310 commit 825c4bc
Showing 1 changed file with 48 additions and 29 deletions.
77 changes: 48 additions & 29 deletions PyRoute/Position/Hex.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@
@author: CyberiaResurrection
"""
import functools
from typing import Tuple
from typing_extensions import TypeAlias

HexPos: TypeAlias = Tuple[int, int]


class Hex(object):

position = None # Hex location
row = 0 # Location in the sector.
col = 0
dx = 0 # location in the whole space, row/column coordinate
dy = 0
q = 0 # location in the whole of space, axial coordinates
r = 0
position: str = None # Hex location
row: int = 0 # Location in the sector.
col: int = 0
dx: int = 0 # location in the whole space, row/column coordinate
dy: int = 0
q: int = 0 # location in the whole of space, axial coordinates
r: int = 0

# Hex-side alias constants
BOTTOM = 1
BOTTOMRIGHT = 2
BOTTOMLEFT = 4

def __init__(self, sector, position):
def __init__(self, sector, position: str):
"""
# The zero point of the co-ordinate system used is Reference (Core 0140).
# As a result, hex position 01,40 becomes q=0, r=0, x=0, y=0, z=0.
Expand All @@ -33,21 +37,39 @@ def __init__(self, sector, position):
self.dx = sector.x * 32 + self.col - 1
self.dy = sector.y * 40 + self.row - 1
self.q, self.r = Hex.hex_to_axial(self.dx, Hex.dy_offset(self.row, sector.y))

def distance(self, other):
return Hex.axial_distance((self.q, self.r), (other.q, other.r))
self._hash = hash((self.position, self.dx, self.dy))

def __str__(self):
return f"{self.col:02d}{self.row:02d}"

def __hash__(self):
return self._hash

def __eq__(self, other):
if self.__hash__() != other.__hash__():
return False
if not isinstance(other, Hex):
return False

if self.position != other.position:
return False
if self.dx != other.dx:
return False
if self.dy != other.dy:
return False
return True

def distance(self, other):
return Hex.axial_distance((self.q, self.r), (other.q, other.r))

# Used to calculate distances for the AllyGen, which keeps only the q/r (axial) coordinates.
@staticmethod
def axial_distance(Hex1, Hex2):
def axial_distance(Hex1: HexPos, Hex2: HexPos):
return Hex._axial_core(Hex1[0] - Hex2[0], Hex1[1] - Hex2[1])

@staticmethod
@functools.cache
def _axial_core(dq, dr):
def _axial_core(dq: int, dr: int):
return (abs(dq) + abs(dr) + abs(dq + dr)) // 2

# Used to calculate distances for the TradeCalculation via the Network Graph, which requires a function
Expand All @@ -60,15 +82,18 @@ def hex_distance(self, star):

@staticmethod
@functools.cache
def _hex_core(dx, dy, dz):
def _hex_core(dx: int, dy: int, dz: int):
return max(abs(dx), abs(dy), abs(dz))

@functools.cache
def hex_position(self):
return (self.q, self.r)
def hex_position(self) -> HexPos:
return self.q, self.r

def get_neighbour(self, direction: int, distance: int = 1):
return Hex.get_neighbor(self.hex_position(), direction, distance)

@staticmethod
def get_neighbor(hex_pos, direction, distance=1):
def get_neighbor(hex_pos: HexPos, direction: int, distance: int = 1) -> HexPos:
"""
determine neighboring hex from the q,r position and direction.
Direction index is:
Expand All @@ -79,38 +104,32 @@ def get_neighbor(hex_pos, direction, distance=1):
4 => Down / left
5 => Down
"""
d = Hex._get_neighbour_core(direction, distance)
return int(hex_pos[0] + d[0]), int(hex_pos[1] + d[1])

@staticmethod
@functools.cache
def _get_neighbour_core(direction, distance):
neighbors = [
[+1, -1], [+1, 0], [0, +1],
[-1, +1], [-1, 0], [0, -1]
]
d = neighbors[direction]
d[0] *= distance
d[1] *= distance
return d
qn = hex_pos[0] + (d[0] * distance)
rn = hex_pos[1] + (d[1] * distance)
return int(qn), int(rn)

@staticmethod
def hex_to_axial(row, col):
def hex_to_axial(row: int, col: int) -> HexPos:
q = row
q_offset = (q + (q & 1)) // 2
r = col - q_offset
return q, r

@staticmethod
def axial_to_hex(q, r):
def axial_to_hex(q: int, r: int):
row = q
q_offset = (q + (q & 1)) // 2
col = r + q_offset

return row, col

@staticmethod
def axial_to_sector(q, r, flip=False):
def axial_to_sector(q: int, r: int, flip: bool = False):
(raw_row, raw_col) = Hex.axial_to_hex(q, r)

col, _ = Hex.dy_reverse(raw_col)
Expand Down

0 comments on commit 825c4bc

Please sign in to comment.