# ryjo.codes

## Conway's Game of Life Written in CLIPS

### Introduction

Conway's Game of Life is a "cellular automation" game. You pick squares on a grid that will start as "alive," then hit play. The game then begins running by itself. It's not necessarily a winners-and-losers kind-of game; rather it's an exercise in mathematical beauty.

In this article, I'll briefly describe how Conway's Game of Life works. I'll also describe some common patterns that do some interesting stuff, including the famous "glider." Finally, I'll provide some CLIPS code that I wrote implementing this famous game. Now: let's get started!

## The Rules

To understand any game, we must first understand the rules. The playing field of Conway's Game of Life is a grid of squares. During a round, a square can be either alive or dead. Whether a square is alive or dead depends on the number of alive squares surrounding that square.

The rules are as follows:

1. A dead square becomes alive if surrounded by exactly 3 squares
2. An alive square stays alive if surrounded by 2 or 3 squares
3. An alive square dies if surrounded by less than 2 or more than 3 squares

Look at the currently alive square A. In the next round, it will remain alive due to the surrounding 3 alive squares B, C, and D. Similarly, the currently dead squares G and F will become alive. Squares B and E will perish. Finally, C and D will remain alive as they are surrounded by 2 alive squares.

This process continues. In the next round, squares H and I will come alive. Squares A and D will die, while the rest will remain alive.

We repeat this process again and again for as long as we'd like. At some point (after 7 rounds, actually), this particular pattern will end with no squares alive.

Seems easy enough! Let's implement it in CLIPS.

### CLIPS Implementation

CLIPS has the ability to call underlying system functions. In this case, we'll be running this in bash in Ubuntu, so we have access to a few programs we can use to draw our playing field. Put this in a file called `life.bat`:

```(system "tput civis")
(reset)
(run)
(system "tput cnorm")
(exit)```

First, we use `tput` to hide the cursor. This will otherwise just get in the way when we render our playing field. Next, we'll `load*` up our rules. We'll separate the generic rules engine and specific playing fields into two separate files. This will allow us to very quickly swap out different patterns as we'd like. We'll then `reset` to initialize our `deffacts`, `run` to play the game, make our cursor visible with `tput cnorm`, and then `exit`.

Alright, next comes the framework rules for our game. Put this into a `life.clp` file:

```(deftemplate alive (slot x) (slot y) (slot tick (default -1)))
(deftemplate next  (slot x) (slot y) (slot tick) (slot surrounding))

(deffacts init
(tick -1)
(height 24)
(width 24)
(max-ticks 25))

(defrule born
(tick ?tick)
(next (x ?x) (y ?y) (tick ?tick) (surrounding 3))
=>
(assert (alive (x ?x) (y ?y) (tick ?tick))))

(defrule survive
(tick ?tick)
(alive (x ?x) (y ?y) (tick ?previous&:(= ?previous (- ?tick 1))))
(next (x ?x) (y ?y) (tick ?tick) (surrounding 2))
=>
(assert (alive (x ?x) (y ?y) (tick ?tick))))

(defrule clean-up
(tick ?tick)
?t <- (tick ?previous&:(= ?previous (- ?tick 1)))
=>
(retract ?t)
(do-for-all-facts ((?n next)) (= ?n:tick ?previous) (retract ?n))
(do-for-all-facts ((?a alive)) (= ?a:tick ?previous) (retract ?a)))

(defrule render-and-tick
(declare (salience -1))
(max-ticks ?max)
(tick ?tick&:(<= ?tick ?max))
(height ?height)
(width ?width)
=>
(system "tput clear")
(bind ?nexttick (+ ?tick 1))
(loop-for-count (?y ?height)
(loop-for-count (?x ?width)
(assert (next (tick ?nexttick)
(x ?x) (y ?y)
(surrounding
(length\$
(find-all-facts ((?a alive))
(and
(= ?a:tick ?tick)
(or (<> ?x ?a:x) (<> ?y ?a:y))
(or (= ?x ?a:x) (= ?x (- ?a:x 1)) (= ?x (+ ?a:x 1)))
(or (= ?y ?a:y) (= ?y (- ?a:y 1)) (= ?y (+ ?a:y 1)))))))))
(if (any-factp ((?a alive)) (and (= ?a:tick ?tick) (= ?a:x ?x) (= ?a:y ?y)))
then (print " # ")
else (print "   ")))
(print crlf))
(system "sleep 0.2")
(assert (tick ?nexttick)))```

First we define a few templates for our facts. `alive` facts will represent squares that are alive and should be rendered as such with a `#`. The `next` template is used to represent which squares should be alive in the next round. We compute this during the current round to capture the number of surrounding `alive` squares.

We then define some initial facts. `tick` is what we'll use to denote rounds. Think of this as the ticking of a clock. As time moves forward, so does Life. `height` and `width` define the size of our playing field. Finally, `max-ticks` tells us how many rounds long this game will be.

The `born` and `survive` Rules are responsible for determining which squares will be alive next round. We use `clean-up` to retract previously rendered `alive` and their corresponding `next` facts.

Finally, `render-and-tick` draws in our terminal. We first clear the terminal with `tput clear`. We then use nested `loop-for-count` calls to get each coordinate on the grid. We first assert a `next` fact for the given coordinate that calculates how many `alive` facts surround it. Then, we render either a `#` (alive) or a blank space (dead) depending on if there is an `alive` fact at that coordinate. We use `length\$` and `find-all-facts` to count the surrounding alive facts.

Now we'll create a `lifedemo.clp` file in which we'll define our initially alive squares:

```(deffacts demo
(alive (x 6) (y 15))
(alive (x 7) (y 14))
(alive (x 7) (y 13))
(alive (x 8) (y 9))
(alive (x 8) (y 8))
(alive (x 8) (y 7))

(alive (x 10) (y 15))
(alive (x 9) (y 15))
(alive (x 8) (y 15))
(alive (x 10) (y 14))
(alive (x 9) (y 14))
(alive (x 8) (y 14))
(alive (x 1) (y 10))
(alive (x 1) (y 11))
(alive (x 2) (y 10))
(alive (x 1) (y 5))
(alive (x 9) (y 5))
(alive (x 9) (y 6))

(alive (x 12) (y 15))
(alive (x 11) (y 14))
(alive (x 12) (y 13))
(alive (x 11) (y 9))
(alive (x 12) (y 8))
(alive (x 12) (y 7))

(alive (x 18) (y 15))
(alive (x 19) (y 14))
(alive (x 20) (y 13))
(alive (x 21) (y 9))
(alive (x 20) (y 8))
(alive (x 18) (y 7))

(alive (x 18) (y 17))
(alive (x 19) (y 17))
(alive (x 18) (y 18))
(alive (x 19) (y 18))
(alive (x 15) (y 12))
(alive (x 16) (y 12))
(alive (x 14) (y 10))
(alive (x 15) (y 10))
(alive (x 18) (y 10))
(alive (x 18) (y 5))
(alive (x 19) (y 5))
(alive (x 20) (y 6))
(alive (x 21) (y 6))
(alive (x 21) (y 5))
(alive (x 21) (y 7))
(alive (x 22) (y 7))

(alive (x 17) (y 9))
(alive (x 24) (y 9))
(alive (x 23) (y 16))
(alive (x 23) (y 14))
(alive (x 23) (y 12))
(alive (x 24) (y 16))
(alive (x 24) (y 15))
(alive (x 24) (y 14))
(alive (x 24) (y 22))
(alive (x 24) (y 23))
(alive (x 23) (y 22))
(alive (x 22) (y 22))
(alive (x 17) (y 8)))```

Now we can run the rules engine with `./clips -f2 life.bat`. We should see something that looks like the first video in this article!

### Cool Patterns and their Implementations

There are many different patterns and behaviors that emerge in Conway's Game of Life. Check out the LifeWiki to see tons more. We'll showcase a few of them in this article next.

#### Oscillators

```(deffacts oscillators
(alive (x 3) (y 10))
(alive (x 4) (y 10))
(alive (x 5) (y 10))

(alive (x 10) (y 10))
(alive (x 11) (y 10))
(alive (x 12) (y 10))
(alive (x 11) (y 11))
(alive (x 12) (y 11))
(alive (x 13) (y 11))

(alive (x 17) (y 13))
(alive (x 18) (y 13))
(alive (x 17) (y 12))
(alive (x 18) (y 12))
(alive (x 19) (y 11))
(alive (x 20) (y 11))
(alive (x 19) (y 10))
(alive (x 20) (y 10)))
```

Blinkers are patterns that repeat themselves for several frames.

```(deffacts pulsar
(alive (x 6) (y 15))
(alive (x 6) (y 14))
(alive (x 6) (y 13))
(alive (x 6) (y 9))
(alive (x 6) (y 8))
(alive (x 6) (y 7))

(alive (x 10) (y 17))
(alive (x 9) (y 17))
(alive (x 8) (y 17))
(alive (x 10) (y 12))
(alive (x 9) (y 12))
(alive (x 8) (y 12))
(alive (x 10) (y 10))
(alive (x 9) (y 10))
(alive (x 8) (y 10))
(alive (x 10) (y 5))
(alive (x 9) (y 5))
(alive (x 8) (y 5))

(alive (x 11) (y 15))
(alive (x 11) (y 14))
(alive (x 11) (y 13))
(alive (x 11) (y 9))
(alive (x 11) (y 8))
(alive (x 11) (y 7))

(alive (x 13) (y 15))
(alive (x 13) (y 14))
(alive (x 13) (y 13))
(alive (x 13) (y 9))
(alive (x 13) (y 8))
(alive (x 13) (y 7))

(alive (x 14) (y 17))
(alive (x 15) (y 17))
(alive (x 16) (y 17))
(alive (x 14) (y 12))
(alive (x 15) (y 12))
(alive (x 16) (y 12))
(alive (x 14) (y 10))
(alive (x 15) (y 10))
(alive (x 16) (y 10))
(alive (x 14) (y 5))
(alive (x 15) (y 5))
(alive (x 16) (y 5))

(alive (x 18) (y 15))
(alive (x 18) (y 14))
(alive (x 18) (y 13))
(alive (x 18) (y 9))
(alive (x 18) (y 7))
(alive (x 18) (y 8)))
```

### Spaceships

Spaceships appear to move across the playing field.

#### Gliders

```(deffacts gliders
(alive (x 3) (y 1))
(alive (x 3) (y 2))
(alive (x 3) (y 3))
(alive (x 2) (y 3))
(alive (x 1) (y 2))

(alive (x 9) (y 3))
(alive (x 9) (y 4))
(alive (x 9) (y 5))
(alive (x 8) (y 5))
(alive (x 7) (y 4))

(alive (x 5) (y 19))
(alive (x 5) (y 20))
(alive (x 5) (y 21))
(alive (x 4) (y 19))
(alive (x 3) (y 20))

(alive (x 18) (y 19))
(alive (x 18) (y 20))
(alive (x 18) (y 21))
(alive (x 19) (y 19))
(alive (x 20) (y 20)))
```

#### Light-weight Spaceships

```(deffacts lightweight-space-ship
(alive (x 2) (y 1))
(alive (x 4) (y 1))
(alive (x 5) (y 2))
(alive (x 5) (y 3))
(alive (x 5) (y 4))
(alive (x 5) (y 5))
(alive (x 2) (y 4))
(alive (x 3) (y 5))
(alive (x 4) (y 5))

(alive (x 7) (y 7))
(alive (x 7) (y 9))
(alive (x 8) (y 10))
(alive (x 9) (y 10))
(alive (x 10) (y 10))
(alive (x 11) (y 10))
(alive (x 11) (y 9))
(alive (x 11) (y 8))
(alive (x 10) (y 7)))```

### Conclusion

Conway's Game of Life can be quite fun to toy around with. It's also a great way to learn a new programming language. CLIPS once again makes it super easy to implement something awesome.

- ryjo