""" Code example from Complexity and Computation, a book about
exploring complexity science with Python.  Available free from
Copyright 2011 Allen B. Downey.
Distributed under the GNU General Public License at gnu.org/licenses/gpl.html.
import numpy
import CADrawer
from CA import CA
class CircularCA(CA):
    """A variation of CA that wraps around so that the cells are
    arranged in a ring.
    def __init__(self, rule, n=100, ratio=2):
        """n, m are the number of rows, columns.
        array is the numpy array that contains the data.
        next is the index of the next empty row.
        self.table = self.make_table(rule)
        self.n = n
        # allocate two extra cells for ghosts
        self.m = ratio*n + 1 + 2
        self.array = numpy.zeros((self.n, self.m), dtype=numpy.int8)
        self.next = 0
    def start_single(self):
        """start with one cell in the left of the top row"""
        self.array[0, 1] = 1
        self.next += 1
    def step(self):
        """Executes one time step by computing the next row of the array."""
        i = self.next
        self.next += 1
        a = self.array
        t = self.table
        # copy the ghost cells
        a[i-1,0] = a[i-1,self.m-2]
        a[i-1,self.m-1] = a[i-1,1]
        for j in xrange(1,self.m-1):
            a[i,j] = t[tuple(a[i-1, j-1:j+2])]
    def get_array(self, start=0, end=None):
        """get a slice of columns from the CA, with slice indices
        (start, end).  We need to add one to avoid ghost cells.
        if end==None:
            return self.array[:, start+1:self.m-1]
            return self.array[:, start+1:end+1]
def main(script, rule=30, n=100, *args):
    rule = int(rule)
    n = int(n)
    ca = CircularCA(rule, n)
    if 'random' in args:
    if 'eps' in args:
        drawer = CADrawer.EPSDrawer()
    elif 'pil' in args:
        drawer = CADrawer.PILDrawer()
        drawer = CADrawer.PyplotDrawer()
    if 'trim' in args:
        drawer.draw(ca, start=n/2, end=3*n/2+1)
if __name__ == '__main__':
    import sys