(ns ^{:doc "Functions to create and to print two dimensional cellular automata. Nothing in this namespace 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." :author "Simon Brooke"} mw-engine.world (:require [clojure.string :as string] [mw-engine.utils :refer [population]])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; mw-engine: the state/transition engine of MicroWorld. ;;;; ;;;; This program is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU General Public License ;;;; as published by the Free Software Foundation; either version 2 ;;;; of the License, or (at your option) any later version. ;;;; ;;;; This program is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;;; GNU General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU General Public License ;;;; along with this program; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ;;;; USA. ;;;; ;;;; Copyright (C) 2014 Simon Brooke ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defmacro 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 "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 (map (fn [h] (apply vector (map #(make-cell % h) (range width)))) (range 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) :else 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)