Source code for seagull.rules
# -*- coding: utf-8 -*-
"""Rules determine how the evolution of the lifeforms will progress. In
Seagull, rules are implemented as a function that takes in a 2-dimensional
array of a given shape then returns the updated array with the rule applied"""
# Import standard library
import re
from typing import Tuple, List
# Import modules
import numpy as np
from scipy.signal import convolve2d
from loguru import logger
# Import from package
[docs]def conway_classic(X) -> np.ndarray:
"""The classic Conway's Rule for Game of Life (B3/S23)"""
return life_rule(X, rulestring="B3/S23")
[docs]def life_rule(X: np.ndarray, rulestring: str) -> np.ndarray:
"""A generalized life rule that accepts a rulestring in B/S notation
Rulestrings are commonly expressed in the B/S notation where B (birth) is a
list of all numbers of live neighbors that cause a dead cell to come alive,
and S (survival) is a list of all the numbers of live neighbors that cause
a live cell to remain alive.
Parameters
----------
X : np.ndarray
The input board matrix
rulestring : str
The rulestring in B/S notation
Returns
-------
np.ndarray
Updated board after applying the rule
"""
birth_req, survival_req = _parse_rulestring(rulestring)
neighbors = _count_neighbors(X)
birth_rule = (X == 0) & (np.isin(neighbors, birth_req))
survival_rule = (X == 1) & (np.isin(neighbors, survival_req))
return birth_rule | survival_rule
def _parse_rulestring(r: str) -> Tuple[List[int], List[int]]:
"""Parse a rulestring"""
pattern = re.compile("B([0-8]+)?/S([0-8]+)?")
if pattern.match(r):
birth, survival = r.split("/")
birth_neighbors = [int(s) for s in birth if s.isdigit()]
survival_neighbors = [int(s) for s in survival if s.isdigit()]
else:
msg = f"Rulestring ({r}) must satisfy the pattern {pattern}"
logger.error(msg)
raise ValueError(msg)
return birth_neighbors, survival_neighbors
def _count_neighbors(X: np.ndarray) -> np.ndarray:
"""Get the number of neighbors in a binary 2-dimensional matrix"""
n = convolve2d(X, np.ones((3, 3)), mode="same", boundary="wrap") - X
return n