65 lines
1.8 KiB
Python
65 lines
1.8 KiB
Python
from enum import IntEnum, auto
|
|
|
|
type Coordinate = tuple[int, int]
|
|
|
|
|
|
class PieceType(IntEnum):
|
|
T_JUNCTION = auto() # Direction is the piece at the "stem" of the T
|
|
STRAIGHT = auto()
|
|
CORNER = auto() # Direction is the more counter-clockwise connection
|
|
NODE = auto()
|
|
|
|
|
|
class Direction(IntEnum):
|
|
UP = 0
|
|
RIGHT = auto()
|
|
DOWN = auto()
|
|
LEFT = auto()
|
|
|
|
@staticmethod
|
|
def from_offset(dx: int, dy: int) -> Direction:
|
|
if (dx != 0 and dy != 0) or abs(dx + dy) != 1:
|
|
raise ValueError(f"({dx}, {dy}) is not a valid direction offset")
|
|
if dx != 0:
|
|
return Direction(dx % 4)
|
|
else:
|
|
return Direction(dy + 1)
|
|
|
|
def flip(self) -> Direction:
|
|
return Direction((self + 2) % 4)
|
|
|
|
|
|
class Piece:
|
|
type: PieceType
|
|
direction: Direction
|
|
locked: bool = False
|
|
|
|
def __init__(self, type: PieceType, direction: Direction = Direction.UP) -> None:
|
|
self.type = type
|
|
self.direction = direction
|
|
|
|
def connected_directions(self) -> list[Direction]:
|
|
match self.type:
|
|
case PieceType.NODE:
|
|
return [self.direction]
|
|
case PieceType.CORNER:
|
|
return [self.direction, Direction((self.direction + 1) % 4)]
|
|
case PieceType.STRAIGHT:
|
|
return [self.direction, Direction((self.direction + 2) % 4)]
|
|
case PieceType.T_JUNCTION:
|
|
return [
|
|
self.direction,
|
|
Direction((self.direction + 1) % 4),
|
|
Direction((self.direction - 1) % 4),
|
|
]
|
|
|
|
def turn_cw(self) -> None:
|
|
if self.locked:
|
|
return
|
|
self.direction = Direction((self.direction + 1) % 4)
|
|
|
|
def turn_ccw(self) -> None:
|
|
if self.locked:
|
|
return
|
|
self.direction = Direction((self.direction - 1) % 4)
|