joseraya
12/3/2011 - 10:34 PM

Game of life clojure implementation

Game of life clojure implementation

(ns life.test.core
  (:use [life.core])
  (:use [clojure.test]))

(def alive 1)
(def dead 0)

(defn cell-at [board x y]
	(nth (nth board y []) x 0))

(defn living-neighbours [board x y]
	(let [	top-left (cell-at board (- x 1) (- y 1))
		top (cell-at board x (- y 1))
		top-right (cell-at board (+ x 1) (- y 1))
		l (cell-at board (- x 1) y)
		r (cell-at board (+ x 1) y)
		bottom-left (cell-at board (- x 1) (+ y 1))
		bottom (cell-at board x (+ y 1))
		bottom-right (cell-at board (+ x 1) (+ y 1))]

		(+ top-left top top-right l r bottom-left bottom bottom-right)))

(defn next-status [board x y]
	(let [ln (living-neighbours board x y)
	      current (cell-at board x y)]
	      (cond 
		(< ln 2) dead 
		(> ln 3) dead 
		(and (= dead current) (= ln 3)) alive  
		:else current)))

(defn next-board [board]
	(map-indexed 
		(fn [y row] (map-indexed 
		    (fn [x cell] (next-status board x y) ) 
		    row)) 
		board))

;;------------------- Tests ------------------- 

(deftest can-find-a-cell

  (is (= dead (cell-at [[dead dead dead]
	  		[dead dead dead]
	  	        [dead dead dead]] 0 0)))

  (is (= alive (cell-at [[dead alive dead]
	  		 [dead dead  dead]
	  		 [dead dead  dead]] 1 0))))

(deftest can-count-living-neighbours
	(is (= 0 (living-neighbours [[dead dead dead]
				     [dead dead dead]
				     [dead dead dead]] 0 0)))

	(is (= 1 (living-neighbours [[dead alive dead]
				     [dead dead dead]
				     [dead dead dead]] 0 0))))

(deftest a-cell-with-less-than-two-living-neighbours-dies
	(is (= dead (next-status  [[dead dead  dead]
				   [dead dead  dead]
				   [dead dead  dead]]  0 0)))

	(is (= dead (next-status  [[dead dead  dead]
				   [dead alive dead]
				   [dead dead  dead]]  1 1)))

	(is (= alive (next-status [[dead alive dead]
				   [dead alive dead]
				   [dead alive dead]] 1 1))))


(deftest a-cell-with-more-than-three-neighbours-dies
	(is (= dead (next-status [[dead alive dead]
				  [dead alive dead]
				  [alive alive alive]] 1 1))))

(deftest a-cell-with-two-or-three-neighbours-remains-the-same
	(is (= alive (next-status [[dead alive dead]
				   [dead alive dead]
				   [alive alive dead]] 1 1)))

	(is (= dead  (next-status [[dead alive dead]
				   [dead alive dead]
				   [dead dead dead]]   0 0))))

(deftest a-dead-cell-with-exactly-three-neighbours-revives
	(is (= alive (next-status [[dead alive dead]
				   [alive alive dead]
				   [dead dead dead]] 0 0))))

(deftest a-new-status-for-the-world-is-correctly-calculated
	(let [curr-s  [[dead  dead  alive]
		       [alive dead  dead]
		       [alive dead  alive]]

	      next-s   [[dead  dead  dead]
			[dead dead  dead]
			[dead  alive dead]]]

	      (is (= next-s (next-board curr-s)))))