# CA_and_Domain_Machines_Scrolling.py
# Scrolling Display of a 1D CA with the following parameters.

# Note: For some reason there is a problem with initialization of pygame
# the first time this is run. Just run again and then it will work or
# run any other program that correctly initializes pygame first.

# N = number cells
# NumSteps = number of timesteps to display
# T = number of timesteps to iterate for
# Range = Range of the CA (i.e. 1 for an ECA)
# RuleNumber = Rule number of the CA (i.e. 54)

# set parameters
CellSize = 4                             # the size of each cell
NumSteps = 150                           # number of timesteps to display
N = 196                                  # number of cells in 1D lattice
T = 150                                  # the number of timesteps to iterate for
Range = 1                                # the CA range
RuleNumber = 54                         # the CA rule number

# import modules
from CA_Functions import *
from Epsilon_Machine_Reconstruction import *
from numpy import *
from numpy.random import *
import pygame
from pygame.locals import *

# set up the display
pygame.init()

black = 0,0,0
white = 255,255,255
red = 255, 0, 0

screen = pygame.display.set_mode([CellSize*N, CellSize*NumSteps])
screen.fill(white)
pygame.display.update()


# determine the CA lookup table
lookup_table = DetermineRule(Range, RuleNumber)
print 'lookup_table =', lookup_table


# generate a random initial state 
state = 7*ones(N,int)
for cell in xrange(N):
    state[cell] = randint(0,2)

# generate an initial state according to the domain of the given ECA rule number
#ECA 18 domain  0,W,0,W,0,W..  W = wildcard)
#M = [   [1,[0,1]], [1,[2,3]], [1,[1,1]], [0,[3,3]]  ]

# ECA 54 Domain {1110...}
M = [   [1,[1,2]], [1,[7,4]], [1,[1,3]], [1,[1,6]], [1,[7,5]], [1,[7,6]], [1,[1,7]], [0,[7,7]]     ] 

# ECA 54 Domain {0001...}
#M = [   [1,[2,1]], [1,[4,7]], [1,[3,1]], [1,[6,1]], [1,[5,7]], [1,[6,7]], [1,[7,1]], [0,[7,7]]     ]      

# ECA 193
#M = [[1, [1, 2]], [1, [3, 4]], [1, [5, 6]], [1, [7, 8]], [1, [9, 10]], [1, [11, 12]], [1, [13, 14]], [1, [15, 16]], [1, [9, 17]], [1, [18, 19]], [1, [25, 14]], [1, [23, 26]], [1, [19, 22]], [1, [27, 12]], [1, [21, 19]],
#                  [1, [24, 16]], [1, [9, 19]], [1, [25, 19]], [1, [19, 26]], [0, [19, 19]], [1, [24, 19]], [1, [27, 19]], [1, [19, 14]], [1, [20, 19]], [1, [19, 16]], [1, [19, 12]], [1, [19, 17]], [1, [23, 19]]] 

# ECA 137
#M = [[1, [1, 2]], [1, [3, 4]], [1, [5, 6]], [1, [7, 8]], [1, [9, 10]], [1, [11, 12]], [1, [13, 14]], [1, [15, 16]], [1, [9, 17]], [1, [18, 19]], [1, [20, 14]], [1, [25, 27]], [1, [19, 23]], [1, [22, 12]], [1, [21, 19]],
#    [1, [24, 16]], [1, [19, 17]], [1, [19, 14]], [1, [25, 19]], [0, [19, 19]], [1, [22, 19]], [1, [19, 12]], [1, [19, 27]], [1, [20, 19]], [1, [19, 16]], [1, [26, 19]], [1, [24, 19]], [1, [9, 19]]] 

# ECA 124
#M = [[1, [1, 2]], [1, [3, 4]], [1, [5, 6]], [1, [7, 8]], [1, [9, 10]], [1, [11, 12]], [1, [13, 14]], [1, [15, 16]], [1, [9, 17]], [1, [22, 15]], [1, [26, 27]], [1, [7, 20]], [1, [15, 24]], [1, [18, 12]], [1, [23, 25]],
#                   [0, [15, 15]], [1, [15, 17]], [1, [15, 27]], [1, [15, 20]], [1, [15, 21]], [1, [9, 15]], [1, [23, 15]], [1, [7, 15]], [1, [15, 12]], [1, [26, 15]], [1, [23, 21]], [1, [18, 15]], [1, [15, 19]]] 

# ECA 110
#M = [[1, [1, 2]], [1, [3, 4]], [1, [5, 6]], [1, [7, 8]], [1, [9, 10]], [1, [11, 12]], [1, [13, 14]], [1, [15, 19]], [1, [9, 18]], [1, [21, 15]], [1, [20, 26]], [1, [7, 27]], [1, [15, 22]], [1, [23, 12]], [1, [24, 25]],
#                  [0, [15, 15]], [1, [15, 17]], [1, [24, 15]], [1, [20, 15]], [1, [9, 15]], [1, [15, 12]], [1, [15, 27]], [1, [15, 26]], [1, [7, 15]], [1, [23, 15]], [1, [24, 17]], [1, [15, 16]], [1, [15, 18]]] 

# ECA 25
#M = [[1, [1, 2]], [1, [3, 4]], [1, [5, 6]], [1, [7, 8]], [1, [9, 10]], [1, [11, 12]], [1, [15, 16]], [1, [17, 8]], [1, [13, 10]], [1, [11, 13]], [1, [13, 16]], [1, [14, 13]], [1, [9, 13]], [0, [13, 13]], [1, [17, 13]],
#                  [1, [13, 12]], [1, [15, 13]], [1, [13, 8]]] 

# ECA 9
#M = [[1, [1, 2]], [1, [3, 4]], [1, [5, 6]], [1, [7, 8]], [1, [9, 10]], [1, [11, 12]], [1, [14, 19]], [1, [18, 8]], [1, [13, 10]], [1, [11, 13]], [1, [13, 19]], [1, [16, 13]], [1, [9, 13]], [0, [13, 13]], [1, [13, 12]],
#                   [1, [13, 8]], [1, [17, 13]], [1, [15, 13]], [1, [15, 8]], [1, [14, 13]]] 

# ECA 107
#M = [[1, [0, 1]], [0, [1, 1]]]

M = sort_DFA(M)
HMC = convert_DFA_to_hidden_markov_chain(M)
state = generate_data(HMC, N)
#print 'state =', state


# iteterate the cellular automata for T timesteps
for t in xrange(T):
    state = IterateState(state, N, Range, lookup_table)

    # first move up the current display one row  
    temp = pygame.Surface( [CellSize*N, CellSize*(NumSteps - 1)] )
    temp.blit(screen,[0,-CellSize])
    screen.blit(temp,[0,0])

    # now update the display to inculde the next row of iterates 
    nextrow = pygame.Surface([CellSize*N,CellSize])
    nextrow.fill(red)

    for n in xrange(N):
        colored_cell = pygame.Surface([CellSize,CellSize])
        if state[n] == 1.0:colored_cell.fill(black)
        if state[n] == 0.0:colored_cell.fill(white)
        nextrow.blit(colored_cell,[n*CellSize,0])

    screen.blit(nextrow, [0, (NumSteps - 1)*CellSize])
    pygame.display.update()
