After a lot of tinkering and pondering over the code, I managed to connect our gui to the core of the program. I even managed to throw in some sort of control using a few buttons and a slider (which determines the size of the board). Now the program works in two modes : One which lets you input an initial configuration and computes the next state on every right click. The user can click on any cell at any time to make it alive. The other mode, dubbed the ‘continous mode’, however lets you modify the board only at the start of the program. Once the user press the right mouse button, the program keeps on displaying subsequent states continuously – which is more fun to watch – and finally settles down in a stable state.
The buttons (widgets) and the slider was created using the wxpython library. For a tutorial, visit zetcode.
I’ve tried to put together the code as neatly as possible and i have made a lot of comments too. I would like to point out that my version of the program has a little problem with the mouse clicks. It was unnoticeable when i was using a mouse but when i used the touchpad of my laptop, i found that in some cases i had to click a cell twice to make it alive.
Use the launch.py script to run the program. And make sure you have the pygame and wxpython libraries installed.
Also, if you think that the programs moves all too quickly)or slowly) in the continous mode, change the framerate of the the display to your liking. To do this, open the display.py file and in line 49, change the value inside pygame.time.Clock().tick() to your desired framerate
I *might* convert the python script into an executable for windows and upload it. The conversion can be done using py2exe, but I again *might* have some enthusiasm left to add even more features to my humble program. If I do, then that’s another post 😉
Now that the ‘core’ of the program is up and running (see the previous post : game of life 101) it’s time to add a little glamour to our ‘life’!
So, here’s the recipe :
Dish name : Graphical interface for the game of life
Ingredients required :
1. Python interpreter and some knowledge in python (easily available at a programming site near you)
2. The pygame module for python. Download pygame here
3. A pygame introduction. I recommend inventing with python. Its a great book and serves as an excellent introduction to python AND pygame.
Find the book here. I dare say that ‘Invent with python’ is the only book you’ll ever need to start writing graphical applications in python in no time!
4. A wee bit of patience and a tiny pinch of interest
Now that we have all the ingredients ready, its time to cook some delicious stuff. First of all, let me show you how the ‘game’ will look like after our dish is ready (look at the picture, stupid! :p )
And let me remind you that this is not going to be the graphical implementation of GOL. Why? Because, in this post, I’d just like to see the graphical display up and running. That is, the user must be able to populate the cells with dots, but updating the cells will have to wait until another post. The display window I create now will be completely independent of the text only game of life I had created earlier. But I have made the code flexible enough to be easily modified to suit our purpose at a later time.
So what does the program do exactly? It allows the user to click on a cell and create a green dot right in the middle of the cell. Period.
So, here’s what I did:
1. Divided the screen into cells by drawing horizontal and vertical lines. This is done by first dividing the width (and height) of the window by the no of cells I want. I am assuming that the window will be a square and hence width=height. If the windows width is 400, I’ll divide the width by 5 to get the length of each cell. I draw a vertical line at every 80 pixels on one side and horizontal lines at every 80 pixels on the other side to get the ‘matrix’.
2. Finding the position of mouse in terms of row and column : I identify each cell with its row number and column number. For example, the cell on the top left corner would be the cell (0,0). To get the column on which the mouse pointer now reside, we first divide the X CO-ORDINATE of the mouse position by the length of each cell. Now since both the mouse position and length of cell are of integer type, dividing the x coordinate by the length of each cell gives an integer which says on which column the mouse pointer is.
For example, assume that the mouse pointer is at the position (120,300). The x coordinate is 120. Let the width of window be 400 and let there be 5 cells (as in the picture). So width of each cell is 80. Now to find the column on which the mouse resides, we divide 120 by 80. Since both are integers, we get 120/80 = 1. (If you do not understand this, go here). And that means our mouse is at column 1. Not that this is the SECOND column in the window since column numbering starts from 0. A similar procedure (using height instead of width and the y coordinate) is used to find out on which row the mouse pointer is at.
3. On every left mouse click, the row and column of the cell on which the mouse click occurred is added (appended) to a list called circle_list. If you are not familiar with lists in python, now might be a good time to do so!
4. A function called draw_circles() draws a green circle (or a dot) on the center of all the cells whose co-ordinates (row and column number) are in the circle_list.
If you need any reference/example regarding the program, feel free to view/try my code. Download it from here. I have thrown some comments here and there inside the file to help any readers who might find themselves completely lost 🙂
In future, we might want the window to pass the information regarding the cells to the ‘core’ of the program to compute the next stage and then display the updated information in the window. To do this, we will be passing on the circle_list to the other classes which will compute the next stage, and then pass back an UPDATED circle_list to the display program. All the display program is to do then is to draw little green circles on the cells in the circle_list (and also remove green circles from the cells that were previously in the list, but not anymore)
As for now, have fun conjuring green dots out of thin air. Until next time 😉
I know I said this would be a program that’s graphical. But I certainly think it would be a rather good idea to get GOL (Game of Life) up and running in text only mode first before jumping into mouse clicks and green cells. Modus operandi? Simple. Make a list of what should be implemented, and how it is intended to be implemented.
“You got to be kidding me! Make a list of what to implement and all that crap? Don’t we all write code on the go? ” – typical reaction when the teacher says “Write an algorithm to print the sum of 2 numbers”. Let me make a few things clear first :
1. This program is more complicated than say, bubble sort, and definitely many times complicated than finding the sum of two numbers. if you are unfamiliar with classes and constructors in object oriented programming, I suggest you to go through any one introduction to python books.
2. I was one of those wanna be coders who thought algorithms and top-down design approach was completely unnecessary as long as you have the *idea*. That works fine for bubble sort, but when we are writing a program that involves a lot of classes and a few pages of code, its very difficult to keep track of things. More so when we write programs that span multiple files. So write down at least vaguely what and how we are going to get things done.
3. Yes. This program is going to span multiple files. Doing so not only gives me a sense of achievement (How many one file software have you encountered? Hint : None) but adds to the total readability of the project.
4. Programming in python makes life a lot more simple. And I’m still more or less a wannabe coder 😉
Let me begin by describing the Game board. When I talked about grids and cells in my last post, there came to my mind only one obvious method to do it : Matrices. The Game board or the “playing area” will necessarily be a matrix with a number of rows and columns. Each ‘element’ or ‘position’ in that matrix can be either dead or alive. The user will provide an initial configuration by marking alive cells with a value of 1 and dead cells with a value of 0. Then, when the user press a particular key, a compute() function will compute the number of alive neighbours for each cell, and then update each cell based on the number of its live neighbours.
My particular version of text only, dumbed down GOL was done using 3 files :
1.game.py : The core file. Contains a Game class whose primary job is just to sit there and call other classes and functions.
2.init.py : Creates an empty matrix and contains functions to let the user input an initial configuration.
3.compute.py : As you might have already guessed, this file contains a ComputeNeighbours class which computes the no of live neighbours of a cell, and a Generate class which updates the cell based on its number of live neighbours
A word on the matrix I used though : I found it a bit hard to swallow but there really are no ‘arrays’ in python. Instead, they have this wonderful stuff called lists which is pretty much a dumbed-down uncomplicated version of arrays. I come from a c background and I spent a considerable amount of time gaping at the screen because I could not for the life of me figure out how to implement two dimensional arrays (our matrix) in python. A friend came to the rescue and this is how i did it :
matrix=[[[0,0]]*no_of_cols for x in range(no_of_rows)]
a list is represented as  in python. So [0,0] is a list and its first element is 0 and the second element is 0 as well. let the no_of_cols be 3. so [0,0]*3 will give you
But here, we have written [[0,0]]*no_of_cols. And THAT gives us [[0,0],[0,0],[0,0]]. Tadaaaaaa – A list of lists!!
let no_of_rows be 3 as well
so [[[0,0]]*no_of_cols for x in range(no_of_rows)] will give us :
And that’s our 3×3 two dimensional matrix! But hey, why is each element in the matrix a list as well? Because, I’ll be using a list to represent each cell. The first value in the list says whether the cell is live (1) or dead (0). The next value tells us the number of live neighbours for a particular cell. For eg, if the user inputs an initial configuration such that all the cells are alive, then the value of the first element in the list representing each cell will be 1. Moreover, all the corner cells will have 3 live neighbours, the cells on boundary will have 5 live neighbours and cells NOT on the boundary will have 8 live neighbours. The matrix is passed on to the ComputeNeighbour class. This is how the no of live neighbours are calculated:
1.First, the location of the cell is determined. A cell can either be on a corner, a row boundary (as in a[i]), ‘a’ is the matrix), a column boundary (a[i]) or not on the edge at all
2. Depending upon the location of the cell, the number of neighbour cells it has also varies. So a different function is called to compute the number of neighbours for each type of cell (that is, whether the cell is on a corner or row_boundary)
3. The number of live neighbours of each cell is written into the second position of the list representing that cell. If the top-left corner cell is alive and it has 2 live neighbours, then the matrix would be :
and so on.
After we compute the number of live neighbours of each cell and feed this data into the matrix, finding the next state of the matrix is easy. Just apply the rules to make each cell dead(0) or alive(1). As far as my program goes, after the user enters the initial configuration, pressing 1 on the keyboard prints out the next state of the matrix. The user inputs 0 to exit the program.
Although I’ll have to make some serious changes in this program when adding the graphical stuff, doing the text only GOL was necessary since in the graphical version, I’d simply be displaying information present in the matrix on to the screen.
I’ve uploaded my version of text only GOL in a zip file :
Don’t go downloading individual files. Press ctrl+s to download the zip file or go to file->download. Ignore the .pyc files. They are automatically generated when you run the .py files for the first time
Even though everything *seemed* very straightforward, I ran into random errors and my code is more or less a mess – even though readable enough. Execute game.py to run the program.