Skip to content

Commit

Permalink
working but HORRIBLY messy and hacky
Browse files Browse the repository at this point in the history
  • Loading branch information
jameslawlor committed Mar 31, 2024
1 parent bc6c502 commit d7e2a64
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 29 deletions.
12 changes: 9 additions & 3 deletions src/pyturmite/constants.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
CANVAS_SIZE = 8
N_STEPS = 6000
N_STEPS = 8342
PLOT_MODE = "animate"
CMAP = "Oranges"
RULESET = "RLLR"
# RULESET = "classic" # 'classic' or 'stateful'
# INSTRUCTIONS = "RCCU"
RULESET = 'stateful'
INSTRUCTIONS = [ # triplet notation (write colour, turn instruction, next state)
[(1, 'R', 0),(1, 'R', 1)], # one state per row, one colour per tuple
[(0, 'N', 0),(0, 'N', 1)],
]
ANIMATION_INTERVAL = 1
PADDING_SIZE = 2 # expand in each direction by this amount of cells
SAVE_ANIMATION = False
FRAME_SKIP = 5
FRAME_SKIP = 1
97 changes: 77 additions & 20 deletions src/pyturmite/turmites.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np
import matplotlib.pylab as plt
from pyturmite.constants import CMAP, RULESET, PADDING_SIZE
from pyturmite.constants import CMAP, RULESET, PADDING_SIZE, INSTRUCTIONS

"""
The colors are modified in a cyclic fashion.
Expand All @@ -18,11 +18,18 @@ def __init__(
y0=0,
dir0="u",
ruleset=RULESET,
instructions=INSTRUCTIONS,
):
self.x = x0
self.y = y0
self.dir = dir0
self.parse_ruleset(ruleset)
self.ruleset = ruleset

if ruleset == "classic":
self.parse_classic_instruction_input(instructions)
elif ruleset == "stateful":
self.parse_stateful_instruction_input(instructions)
self.state = 0 # TODO: Get from input instructions instead

def __str__(self):
return str(vars(self))
Expand All @@ -47,34 +54,65 @@ def turn_counter_clockwise(self):
elif self.dir == "r":
self.dir = "u"

def rule_to_func(self, rule):
if rule == "R":
def make_u_turn(self):
if self.dir == "u":
self.dir = "d"
elif self.dir == "l":
self.dir = "r"
elif self.dir == "d":
self.dir = "u"
elif self.dir == "r":
self.dir = "l"

def no_turn(self):
pass

def instruction_to_func(self, instruction):
if instruction == "R":
return self.turn_clockwise
elif rule == "L":
elif instruction == "L":
return self.turn_counter_clockwise

def parse_ruleset(self, ruleset):
elif instruction == "U" or instruction == "B":
return self.make_u_turn
elif instruction == "C" or instruction == "F" or instruction == "N":
return self.no_turn
else:
raise ValueError(f"Instruction {instruction} not recognised! Check inputs!")

def parse_classic_instruction_input(self, instructions):
# TODO: Check validity

self.cmap = plt.get_cmap(CMAP)
colours = self.cmap(np.linspace(0.0, 1, len(ruleset)))
colours = self.cmap(np.linspace(0.0, 1, len(instructions)))

self.rules = {}
self.instructions = {}

for ix, rule in enumerate(ruleset):
self.rules[ix] = {
for ix, instruction in enumerate(instructions):
self.instructions[ix] = {
"colour": colours[ix],
"instruction": self.rule_to_func(rule),
"instruction": self.instruction_to_func(instruction),
}

self.n_colours = len(colours)

def parse_stateful_instruction_input(self, input_instructions):
"""
row = state
col = colour
"""
# TODO: Check validity
self.cmap = plt.get_cmap(CMAP)
colours = self.cmap(np.linspace(0.0, 1, len(input_instructions[0])))
self.n_colours = len(colours)
self.n_states = len(input_instructions)
self.instructions_stateful = np.array(input_instructions)

def init_grid(self, canvas_size, offset=True):
if offset:
self.x = self.x + int(canvas_size / 2)
self.y = self.y + int(canvas_size / 2)

self.grid = np.zeros((canvas_size, canvas_size))
self.grid = np.zeros((canvas_size, canvas_size), dtype=int)

def move(self):
if self.dir == "u":
Expand All @@ -87,20 +125,39 @@ def move(self):
self.x += 1

def check_square_colour(self, i, j):
return self.grid[i, j]
return int(self.grid[i, j])

def change_colour(self, i, j):
self.grid[i, j] = (self.grid[i, j] + 1) % self.n_colours

def turn(self, colour):
turn_instruction = self.rules[colour]["instruction"]
def turn_classic(self, colour):
turn_instruction = self.instructions[colour]["instruction"]
turn_instruction()

def turn_stateful(self, colour, state):
colour_state_tuple = self.instructions_stateful[state][colour]

# change state
self.state = int(colour_state_tuple[-1])
# change colour
colour_to_write = int(colour_state_tuple[0])
self.grid[self.x, self.y] = colour_to_write
print(colour, state, colour_state_tuple, colour_to_write, self.state)
# move instruction
instruction = colour_state_tuple[1]
self.instruction_to_func(instruction)()

def update(self):
colour = self.check_square_colour(self.x, self.y)
self.turn(colour)
self.change_colour(self.x, self.y)
self.move()
if self.ruleset == "classic":
colour = self.check_square_colour(self.x, self.y)
self.turn_classic(colour)
self.change_colour(self.x, self.y)
self.move()

elif self.ruleset == "stateful":
colour = self.check_square_colour(self.x, self.y)
self.turn_stateful(colour, self.state)
self.move()

# expand canvas/grid if we moved outside it
if (
Expand Down
14 changes: 8 additions & 6 deletions src/pyturmite/utils/plotters.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ def animate(self, turmite, n_steps):
)
ax = plt.gca()
frame_num = ax.text(
0.99,
0.99,
0.01,
'',
"",
fontsize=5,
horizontalalignment='right',
verticalalignment='bottom',
horizontalalignment="right",
verticalalignment="bottom",
transform=ax.transAxes,
)
frame_num.set_bbox(dict(facecolor='white', alpha=0.3, edgecolor='black', lw=.1))
)
frame_num.set_bbox(
dict(facecolor="white", alpha=0.3, edgecolor="black", lw=0.1)
)
plt.axis("off")

def update(step, turmite, skip=FRAME_SKIP):
Expand Down

0 comments on commit d7e2a64

Please sign in to comment.