85 lines
2.7 KiB
Clojure
85 lines
2.7 KiB
Clojure
;; Functions to create and to print two dimensional cellular automata. Nothing in this
|
|
;; file should determine what states are possible within the automaton, except for the
|
|
;; initial state, :new.
|
|
;;
|
|
;; A cell is a map containing at least values for the keys :x, :y, and :state.
|
|
;;
|
|
;; A world is a two dimensional matrix (sequence of sequences) of cells, such
|
|
;; that every cell's :x and :y properties reflect its place in the matrix.
|
|
|
|
(ns mw-engine.world
|
|
(:use mw-engine.utils)
|
|
(:require [clojure.string :as string :only [join]]))
|
|
|
|
(defn- make-cell
|
|
"Create a minimal default cell at x, y
|
|
|
|
* `x` the x coordinate at which this cell is created;
|
|
* `y` the y coordinate at which this cell is created."
|
|
[x y]
|
|
{:x x :y y :state :new})
|
|
|
|
(defn- make-world-row
|
|
"Make the (remaining) cells in a row at this height in a world of this width.
|
|
|
|
* `index` x coordinate of the next cell to be created;
|
|
* `width` total width of the matrix, in cells;
|
|
* `height` y coordinate of the next cell to be created."
|
|
[index width height]
|
|
(cond (= index width) nil
|
|
true (cons (make-cell index height)
|
|
(make-world-row (inc index) width height))))
|
|
|
|
(defn- make-world-rows [index width height]
|
|
"Make the (remaining) rows in a world of this width and height, from this
|
|
index.
|
|
|
|
* `index` y coordinate of the next row to be created;
|
|
* `width` total width of the matrix, in cells;
|
|
* `height` total height of the matrix, in cells."
|
|
(cond (= index height) nil
|
|
true (cons (apply vector (make-world-row 0 width index))
|
|
(make-world-rows (inc index) width height))))
|
|
|
|
(defn make-world
|
|
"Make a world width cells from east to west, and height cells from north to
|
|
south.
|
|
|
|
* `width` a natural number representing the width of the matrix to be created;
|
|
* `height` a natural number representing the height of the matrix to be created."
|
|
[width height]
|
|
(apply vector (make-world-rows 0 width height)))
|
|
|
|
(defn truncate-state
|
|
"Truncate the print name of the state of this cell to at most limit characters."
|
|
[cell limit]
|
|
(let [s (:state cell)]
|
|
(cond (> (count (str s)) limit) (subs s 0 limit)
|
|
true s)))
|
|
|
|
(defn format-cell
|
|
"Return a formatted string summarising the current state of this cell."
|
|
[cell]
|
|
(format "%10s(%2d/%2d)"
|
|
(truncate-state cell 10)
|
|
(population cell :deer)
|
|
(population cell :wolves)))
|
|
|
|
(defn- format-world-row
|
|
"Format one row in the state of a world for printing."
|
|
[row]
|
|
(string/join (map format-cell row)))
|
|
|
|
(defn print-world
|
|
"Print the current state of this world, and return nil.
|
|
|
|
* `world` a world as defined above."
|
|
[world]
|
|
(println)
|
|
(dorun
|
|
(map
|
|
#(println
|
|
(format-world-row %))
|
|
world))
|
|
nil)
|