52 lines
1.2 KiB
Python
52 lines
1.2 KiB
Python
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
from typing import Generator
|
|
|
|
|
|
@dataclass
|
|
class CellUpdate:
|
|
x: int
|
|
y: int
|
|
data: dict
|
|
|
|
|
|
class Rule(ABC):
|
|
@abstractmethod
|
|
def step(
|
|
self, x: int, y: int, cell: dict, grid: "Grid"
|
|
) -> Generator[CellUpdate, None, None]:
|
|
pass
|
|
|
|
|
|
class SimpleMapping(Rule):
|
|
def __init__(self, prop, mapping):
|
|
self.mapping = mapping
|
|
self.prop = prop
|
|
|
|
def step(self, x, y, cell, grid):
|
|
yield CellUpdate(x, y, {self.prop: self.mapping.get(cell.get(self.prop))})
|
|
|
|
|
|
class Movement(Rule):
|
|
def __init__(self, prop, dx, dy):
|
|
self.prop = prop
|
|
self.dx = dx
|
|
self.dy = dy
|
|
|
|
def step(self, x, y, cell, grid):
|
|
yield CellUpdate(x + self.dx, y + self.dy, cell)
|
|
|
|
|
|
class Combine(Rule):
|
|
def __init__(self, *rules):
|
|
self.rules = rules
|
|
|
|
def step(self, x, y, cell, grid):
|
|
updates = list(self.rules[0].step(x, y, cell, grid))
|
|
for rule in self.rules[1:]:
|
|
next_updates = []
|
|
for upd in updates:
|
|
next_updates.extend(rule.step(upd.x, upd.y, upd.data, grid))
|
|
updates = next_updates
|
|
yield from updates
|