Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
class XY(NamedTuple) solution in Clear category for Find Enemy by Phil15
# This page is useful when it comes to hexagonal grids.
# https://www.redblobgames.com/grids/hexagons/
from math import atan2, degrees, sqrt
from typing import NamedTuple, Union
# Imagine A1 as center.
NWSE = { 'N': (-1, 0),
'NW': (-1, -1), 'NE': (-1, 1),
'SW': (0, -1), 'SE': (0, 1),
'S': (1, 0)}
class XY(NamedTuple): # To create points and vectors in 2D.
x: Union[int, float]
y: Union[int, float]
def __sub__(pt1, pt2):
"""Subtract coordinates."""
return XY(pt1.x - pt2.x, pt1.y - pt2.y)
def angle(vect1, vect2) -> float:
"""Angle between two vectors (degrees between -180 and 180)."""
rad = atan2(vect1.y, vect1.x) - atan2(vect2.y, vect2.x)
result = (degrees(rad) + 180) % 360 - 180
return round(result, 13)
def relative_direction(vect, dir_vect) -> str:
"""Our relative direction from a direction vector."""
angle = vect.angle(dir_vect)
if abs(angle) < 60:
return 'F'
if abs(angle) > 120:
return 'B'
return 'RL'[angle > 0]
@staticmethod
def from_rowcol(row: int, col: int):
"""Convert (row, col) coords to cartesian coords XY(x, y)."""
return XY(sqrt(3) / 2 * col, - row - (col % 2) / 2)
def cube_distance(a, b):
"""Distance between two hexagonal cells (in cube coords system)."""
return max(map(abs, map(int.__sub__, a, b)))
def rc2cube(pt):
"""Convert (row, col) coords to cube coords."""
r, c = pt
return c, - c - r + c // 2, r - c // 2
def find_enemy(you, direction, enemy):
# Convert to (row, col) coords.
you = int(you[1]) - 1, ord(you[0]) - ord('A')
enemy = int(enemy[1]) - 1, ord(enemy[0]) - ord('A')
# Angles are easy enough with cartesian coords, not with others.
enemy_dir = XY.from_rowcol(*enemy) - XY.from_rowcol(*you)
current_dir = XY.from_rowcol(*NWSE[direction])
return (
enemy_dir.relative_direction(current_dir),
# Hexagonal distances are easier with cube coords.
cube_distance(*map(rc2cube, (you, enemy))),
)
April 15, 2020
Comments: