joi, 6 ianuarie 2011

Conways' game of life, a more natural approach

A few weeks ago, I attended a local programming event, entitled Code Retreat. The main purpose was to give coders a chance to focus on something other than designing / implementing features and meeting deadlines. The main focus of the event was the code itself. We had to code a version of Conway's game of life, but instead of actually finishing the task, we had to develop the application in pairs and follow some rules which underline Agile practices, for instance, all methods should be shorter than 8,6 or 4 (easy, medium, hard) lines, don't use cycles, don't use conditional statements, use very descriptive variable and method names etc.

I never thought just messing around with code could be so much fun. By the end of the event we have experienced multiple ways of implementing the application, and I have learned quite a bit of very handy tricks for coding. The ideas we discussed persisted in my head for many days and I wanted to have another go at implementing the application, since none of us got the chance to finish it at the event.

Here is what it looks like, the final version, because after getting the basics down (e.g. cells, universe,  iterations etc.), I just added stuff to it: Life game.

Let me say a few words about the code. First thing, I used the Parsley framework to develop it, because it is perfect for quick development of Flex applications, then there are a few details that are worth mentioning, regarding the dynamics of the game.

When implementing the application, there are basically two paths you can go by: the first would be to focus on the universe - which is to say, the grid that holds the cells (its most simple form is a n x n matrix, consisting of "dead cells") - specifically, at each iteration, the grid parses all the locations and updates the cells accordingly (the living ones that don't match the conditions die, and the dead ones that do meet the conditions, come alive).

Then, the second way is to focus on the cell. Each cell holds its number of living neighbors, it has two states (alive/dead), and it can update itself. The grid just parses all cells, passes the number of living neighbors to each cell, and lets it know when to update its state.

Both of these solutions work equally well in practice, and implementing one of the two is basically a matter of preference. However, in my opinion, none of them seem to reflect the way our natural universe actually works. What I mean, is that the universe does not consist of "dead cells" that "come alive" according to some rules, and another thing, once a cell dies, it shouldn't be able to come alive again (i.e. it shouldn't be allocated in memory). The universe should just manage the living cells, then spawn new ones and finally remove dead cells forever (yeah I know, it's an oversimplification but I feel it reflects the best way of how our universe works). So instead of actually having a grid of dead cells, we just need to have a list of living cells and let them do their business. This way we balance the focus between the universe and the cell.

The next problem to solve is how to instruct the cells to multiply. Again, we can look to our universe for an answer. If we assume that a cell is aware of its own position in the universe (in this case a 2D grid), the natural thing for it to (want to) do, is to multiply in all available directions (NW, N, NE, W, E, SW, S, SE) - as a side-note, I got this idea from Richard Dawkins' book The selfish gene - because a cell shoud not "care" if it can or not multiply on a specific location, it's just "wired" to do so; the universe should "tell" the cell if it can spawn an offspring at a particular location, or not - as we are about to see. OK, now that we got that down, our application is starting to function more and more like the real universe.

Now the only problem that remains, is how to spawn new cells in the universe. Let's do a quick recap:

1. The universe consists only of the living cells.
2. Cells spawn their offspring in the adjacent locations to their position, 8 in number.

According to the game rules, a new cell is born if it has three living neighbors, which is the same as saying "a new cell is born on a particular location, if three already living cells want to spawn their offspring on that same location". This way, it's like three organisms need to "come together" in order to create new life... talk about a menage a trois :)

So this way, the universe is responsible for "telling" the cells if they are allowed to multiply or not, being according to the game rules, or within the grid limits. In fact, the cells don't even know if one of their spawn locations was used to spawn a new cell, nor should they care. And correct me if I'm wrong, but this method reflects how the universe actually works, in principle at least :). So the final flow of the application looks like this:

1. The universe consists only of the living cells.
2. Determine all the locations in which cells want to spawn their offspring.
3. The universe parses those spawn locations and looks for triplicates.
4. The universe spawns new cells on locations that can be classified as triplicates.

Feel free to check out the application here (view source enabled) and let me know what you think.


'Till next time, take care!

Niciun comentariu:

Trimiteți un comentariu