2015-05-31 03:36:35 +00:00
|
|
|
"""
|
|
|
|
|
2015-06-01 12:30:00 +00:00
|
|
|
@author: jrpotter
|
|
|
|
@date: June 01, 2015
|
2015-05-31 03:36:35 +00:00
|
|
|
"""
|
2015-06-01 02:19:50 +00:00
|
|
|
import time
|
2015-06-01 00:58:09 +00:00
|
|
|
import copy
|
2015-06-01 02:19:50 +00:00
|
|
|
|
2015-06-01 12:30:00 +00:00
|
|
|
import camtools
|
2015-06-01 00:58:09 +00:00
|
|
|
import ruleset as rs
|
|
|
|
import neighborhood as nh
|
2015-05-31 03:36:35 +00:00
|
|
|
|
2015-06-01 02:19:50 +00:00
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
import matplotlib.animation as ani
|
|
|
|
|
2015-05-31 03:36:35 +00:00
|
|
|
|
|
|
|
class CAM:
|
|
|
|
"""
|
|
|
|
Represents a Cellular Automata Machine (CAM).
|
|
|
|
|
2015-05-31 22:27:47 +00:00
|
|
|
The CAM consists of any number of cell planes that allow for increasingly complex cellular automata.
|
2015-05-31 03:36:35 +00:00
|
|
|
This is the top-level module that should be used by anyone wanting to work with fifth, and provides
|
|
|
|
all methods needed (i.e. supported) to interact/configure the cellular automata as desired.
|
|
|
|
"""
|
|
|
|
|
2015-06-01 12:30:00 +00:00
|
|
|
def __init__(self, cps=1, dimen=(100, 100)):
|
2015-05-31 20:09:33 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
"""
|
2015-06-01 12:30:00 +00:00
|
|
|
self.planes = np.zeros((max(cps, 1),) + dimen, dtype=np.int32)
|
|
|
|
self.master = self.planes[0]
|
2015-06-01 02:19:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
def start_plot(self, clock, ruleset, neighborhood, *args):
|
|
|
|
"""
|
|
|
|
Initiates the main loop.
|
|
|
|
|
|
|
|
The following function displays the actual graphical component (through use of matplotlib), and triggers the
|
|
|
|
next tick for every "clock" milliseconds.
|
|
|
|
"""
|
|
|
|
fig, ax = plt.subplots()
|
|
|
|
|
|
|
|
ax.set_frame_on(False)
|
|
|
|
ax.get_xaxis().set_visible(False)
|
|
|
|
ax.get_yaxis().set_visible(False)
|
|
|
|
|
2015-06-01 12:30:00 +00:00
|
|
|
mshown = plt.matshow(self.master, fig.number)
|
2015-06-01 02:19:50 +00:00
|
|
|
|
|
|
|
def animate(frame):
|
|
|
|
self.tick(ruleset, neighborhood, *args)
|
2015-06-01 12:30:00 +00:00
|
|
|
mshown.set_array(self.master)
|
2015-06-01 02:19:50 +00:00
|
|
|
fig.canvas.draw()
|
|
|
|
|
|
|
|
ani.FuncAnimation(fig, animate, interval=clock)
|
|
|
|
|
|
|
|
plt.axis('off')
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
|
|
|
def start_console(self, clock, ruleset, neighborhood, *args):
|
|
|
|
"""
|
|
|
|
|
|
|
|
"""
|
|
|
|
while True:
|
2015-06-01 12:30:00 +00:00
|
|
|
print(self.master)
|
2015-06-01 02:19:50 +00:00
|
|
|
time.sleep(clock / 1000)
|
|
|
|
self.tick(ruleset, neighborhood, *args)
|
2015-05-31 20:09:33 +00:00
|
|
|
|
|
|
|
|
2015-05-31 22:27:47 +00:00
|
|
|
def tick(self, ruleset, neighborhood, *args):
|
2015-05-31 03:36:35 +00:00
|
|
|
"""
|
2015-05-31 20:09:33 +00:00
|
|
|
The tick function should be called whenever we want to change the current status of the grid.
|
2015-05-31 03:36:35 +00:00
|
|
|
|
2015-05-31 20:09:33 +00:00
|
|
|
Every time the tick is called, the ruleset is applied to each cell and the next configuration
|
|
|
|
is placed into the master grid. Depending on the timing specifications set by the user, this
|
2015-05-31 22:27:47 +00:00
|
|
|
may also change secondary cell planes (the master is always updated on each tick).
|
2015-05-31 03:36:35 +00:00
|
|
|
"""
|
2015-06-01 12:30:00 +00:00
|
|
|
tmp = np.copy(self.master)
|
|
|
|
for i in range(len(self.master.flat)):
|
|
|
|
tmp.flat[i] = ruleset.call(i, self.master, neighborhood, *args)
|
|
|
|
self.master[:] = tmp
|
2015-06-01 00:58:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
def randomize(self):
|
|
|
|
"""
|
|
|
|
Set the master grid to a random configuration.
|
|
|
|
"""
|
2015-06-01 12:30:00 +00:00
|
|
|
self.master[:] = np.random.random_integers(0, 1, self.master.shape)
|
2015-05-31 20:09:33 +00:00
|
|
|
|