92 lines
3.0 KiB
Python
92 lines
3.0 KiB
Python
|
from enum import Enum
|
|||
|
from typing import NamedTuple, Optional
|
|||
|
|
|||
|
|
|||
|
class Coords(NamedTuple):
|
|||
|
"""
|
|||
|
Вспомогательный класс для упрощения работы с координатами
|
|||
|
"""
|
|||
|
|
|||
|
x: int | float
|
|||
|
y: int | float
|
|||
|
|
|||
|
def __add__(self, other):
|
|||
|
if isinstance(other, self.__class__):
|
|||
|
return self.__class__(self.x + other.x, self.y + other.y)
|
|||
|
if isinstance(other, (int, float)):
|
|||
|
return self.__class__(self.x + other, self.y + other)
|
|||
|
return NotImplemented
|
|||
|
|
|||
|
def __sub__(self, other):
|
|||
|
if isinstance(other, self.__class__):
|
|||
|
return self.__class__(self.x - other.x, self.y - other.y)
|
|||
|
if isinstance(other, (int, float)):
|
|||
|
return self.__class__(self.x - other, self.y - other)
|
|||
|
return NotImplemented
|
|||
|
|
|||
|
def __floordiv__(self, other):
|
|||
|
if isinstance(other, self.__class__):
|
|||
|
return self.__class__(self.x // other.x, self.y // other.y)
|
|||
|
if isinstance(other, (int, float)):
|
|||
|
return self.__class__(self.x // other, self.y // other)
|
|||
|
return NotImplemented
|
|||
|
|
|||
|
def __mul__(self, other):
|
|||
|
if isinstance(other, self.__class__):
|
|||
|
return self.__class__(self.x * other.x, self.y * other.y)
|
|||
|
if isinstance(other, (int, float)):
|
|||
|
return self.__class__(self.x * other, self.y * other)
|
|||
|
return NotImplemented
|
|||
|
|
|||
|
def transform(self, ref: "Coords"):
|
|||
|
return self * ref
|
|||
|
|
|||
|
def dir_norm(self):
|
|||
|
"""нормализация вектора, но только для получения направления
|
|||
|
x, y могут быть только -1, 0, 1
|
|||
|
может быть только направление по горизонтали либо по вертикали
|
|||
|
либо без направления
|
|||
|
"""
|
|||
|
src = self
|
|||
|
if self.x and self.y:
|
|||
|
src = (
|
|||
|
self.__class__(self.x, 0)
|
|||
|
if abs(self.x) > abs(self.y)
|
|||
|
else self.__class__(0, self.y)
|
|||
|
)
|
|||
|
return self.__class__(*((n > 0) - (n < 0) for n in src))
|
|||
|
|
|||
|
@classmethod
|
|||
|
def zero(cls):
|
|||
|
return cls(0, 0)
|
|||
|
|
|||
|
|
|||
|
class Direction(Enum):
|
|||
|
LEFT = 1
|
|||
|
RIGHT = 2
|
|||
|
UP = 3
|
|||
|
DOWN = 4
|
|||
|
|
|||
|
def as_coords(self):
|
|||
|
match self:
|
|||
|
case Direction.LEFT:
|
|||
|
return Coords(-1, 0)
|
|||
|
case Direction.RIGHT:
|
|||
|
return Coords(1, 0)
|
|||
|
case Direction.UP:
|
|||
|
return Coords(0, -1)
|
|||
|
case Direction.DOWN:
|
|||
|
return Coords(0, 1)
|
|||
|
|
|||
|
@staticmethod
|
|||
|
def from_coords(coords: Coords) -> Optional["Direction"]:
|
|||
|
match coords.dir_norm():
|
|||
|
case Coords(-1, 0):
|
|||
|
return Direction.LEFT
|
|||
|
case Coords(1, 0):
|
|||
|
return Direction.RIGHT
|
|||
|
case Coords(0, -1):
|
|||
|
return Direction.UP
|
|||
|
case Coords(0, 1):
|
|||
|
return Direction.DOWN
|