Saturday, May 9, 2015

I am the Game of Life. Play me.



## This post is meant to be copied and pasted into a text        
## file with a .py extension and run as a python programme.  
## If you are using Windows, you can download the  
## Windows X86 MSI Python 2.7.9 installer from the www.python.org   
## website. I wrote the programme, based on John Conway's  
## Game of Life to learn more about Python and especially Tkinter. 
## Tkinter is a bit of a disappointment but I'm pleased with
## the results.       
##               
## It was John Conway, the Liverpudlian mathematician, who
## invented the game in 1970. He first played it on paper and
## pencil rather than computer, and even the thought of this is
## exhausting. It's not hard to see what computers have done
## for new fields of math. The Game of Life is credited to have
## helped in opening up the study of Cellular Automata. It's
## really not a game in the conventional sense, but it's fun
## to watch.
##
## Each red cell, or square, is a living organism. And each cell
## is surrounded by 8 other neighbouring cells. If a living red 
## cell is surrounded by 0 or only 1 other red cell, that cell will
## die in the next generation. Die of loneliness, I suppose. To
## die means to be replaced by a yellow cell. Similarly, if the
## red cell is surrounded by 4 to 8 other red cells, that cell
## will die in the next generation of over-crowding. A red cell
## will survive and continue to live in the next generation if it
## is surrounded by 2 or 3 neighbouring red cells. One more rule,
## if a yellow cell is surrounded by exactly 3 red cells, it will
## come to life in the next generation and be replaced by a red 
## cell. You can read Martin Gardner's original introduction to 
## the game in his 1970 column in Scientific American. 
##  
#!/usr/bin/env python2

import Tkinter as tk

def quitgame():
    root.destroy()

def advance1():
    gen_number = 1
    advance(gen_number)
    
def advance10():
    gen_number = 10
    advance(gen_number)

def advance100():
    gen_number = 100
    advance(gen_number)

def advanceinfinity():
    gen_number = 100000
    advance(gen_number)

def advance(gen_number):
    global tally
    for k in range (gen_number):
        ##main loop to check neighbours
        for x in range (25):
            for y in range (42):
                Matrix[x][y][1] = 0

                if Matrix[x][y][0] == 6:        
                    colour_flag = 'red'
                    tally_neighbours(x,y)
                else:
                    colour_flag = 'yellow'
                    tally_neighbours(x,y)

                if (tally>3 or tally < 2) and colour_flag=='red':
                    Matrix[x][y][1] = 7
                    A=tk.Button(frame2, bg='yellow')
                    A.grid(row=x,column=y)
                    frame2.grid()

                if tally == 3 and colour_flag == 'yellow':                    
                    Matrix[x][y][1] = 5
                    A=tk.Button(frame2, bg='red')
                    A.grid(row=x,column=y)
                    frame2.grid()

                tally = 0
            root.update()

        for x in range (25):   
            for y in range (42): 
            ## transferring info from 3rd to 2nd dimension
                if Matrix[x][y][1] == 5:
                    Matrix[x][y][0] = 6
                if Matrix[x][y][1] == 7:
                    Matrix[x][y][0] = 0

def tally_neighbours(x,y):
    global tally
    if x!=0 and y !=0 and Matrix[x-1][y-1][0]==6:
        ## for checking surrounding 8 squares
        ## of middle cell
        tally = tally + 1                              
    if x!=0 and y !=0 and Matrix[x-1][y][0]==6:
        tally = tally + 1
    if x!=0 and y !=0 and Matrix[x][y-1][0]==6:
        tally = tally + 1
    ## these try statements make sure
    ## no error message occurs when i
    ## overstep the bounds positively.
    ## Negative overstepping is not OK
    try:                                                
        if x!=0 and y !=0 and Matrix[x+1][y+1][0]==6:   
             tally = tally + 1                          
    except IndexError:                                  
        pass
    try:
        if x!=0 and y !=0 and Matrix[x][y+1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x!=0 and y !=0 and Matrix[x+1][y][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x!=0 and y !=0 and Matrix[x-1][y+1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x!=0 and y !=0 and Matrix[x+1][y-1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
########################
## for checking 5 squares surrounding
## top row cell
    if x == 0 and y != 0 and Matrix[0][y-1][0]==6:      
        tally = tally + 1                               
    try:
        if x == 0 and y !=0 and Matrix[0][y+1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x == 0 and y !=0 and Matrix[1][y][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:              
        if x == 0 and y !=0 and Matrix[1][y-1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x == 0 and y !=0 and Matrix[1][y+1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
#########################
## for checking 5 cells surrounding
## left column cell
    if x != 0 and y == 0 and Matrix[x-1][0][0]==6:      
        tally = tally + 1                               
    try:
        if x != 0 and y == 0 and Matrix[x-1][1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x != 0 and y == 0 and Matrix[x][1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x != 0 and y == 0 and Matrix[x+1][0][0]==6:
            tally = tally + 1
    except IndexError:
        pass
    try:
        if x != 0 and y == 0 and Matrix[x+1][1][0]==6:
            tally = tally + 1
    except IndexError:
        pass
#################
## for checking 3 cells surrounding
## top left cell
    if x == 0 and y == 0 and Matrix[0][1][0]==6:       
        tally = tally + 1                               
    if x == 0 and y == 0 and Matrix[1][0][0]==6:
        tally = tally + 1
    if x == 0 and y == 0 and Matrix[1][1][0]==6:
        tally = tally + 1
    return tally
## for choosing (and correcting) initial configuration
def startMove(i,j,event):               
    if Matrix[i][j][0]== 0:
        event.widget.config(bg='red')
        Matrix[i][j][0]=6
    else:
        event.widget.config(bg='yellow')
        Matrix[i][j][0]=0
    
root = tk.Tk()

Matrix = [[[0 for z in range(2)] for y in range (42)] for x in range (25)]

tally = 0

frame1 = tk.Frame(root)
frame2 = tk.Frame(root)

instruct = tk.Label(frame1, text="Initialize the game by clicking on a few yellow squares. ")
instruct.pack(side=tk.TOP)
onebutton = tk.Button(frame1, text="Advance 1 generation", command=advance1)
onebutton.pack(side=tk.LEFT)
tenbutton = tk.Button(frame1, text="Advance 10", command=advance10)
tenbutton.pack(side=tk.LEFT)
hundredbutton = tk.Button(frame1, text="Advance 100", command=advance100)
hundredbutton.pack(side=tk.LEFT)
infinitybutton = tk.Button(frame1, text="Advance forever", command=advanceinfinity)
infinitybutton.pack(side=tk.LEFT)
quitbutton = tk.Button(frame1, text="Quit", command=quitgame)
quitbutton.pack(side=tk.LEFT)
frame1.grid()

for x in range (25):
    for y in range (42):
        A=tk.Button(frame2, bg='yellow')
        A.grid(row=x,column=y)
        frame2.grid()
        A.bind('', lambda e, x=x, y=y: startMove(x, y, e))

root.title("Martin's Conway's Game Of Life")
root.mainloop()

No comments:

Post a Comment