Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add __eq__ to Hex, & type-hint it #138

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading