Feature complete for version 1; some refactoring still needed.

This commit is contained in:
Simon Brooke 2014-07-24 18:44:04 +01:00
parent a0f59ac2dd
commit 98e43dbe8f
10 changed files with 190 additions and 84 deletions

View file

@ -1,5 +1,6 @@
## What this is about ## What this is about
<img alt="Screenshot" id="screenshot" style="float: left; padding-right: 2em;" src="img/screenshot_med.png"/>
MicroWorld is a rule driven cellular automaton. What does that mean? Well, it's MicroWorld is a rule driven cellular automaton. What does that mean? Well, it's
a two dimensional world made up of squares called **cells**. The world develops a two dimensional world made up of squares called **cells**. The world develops
in steps, and at each step, each cell is modified by applying the rules. in steps, and at each step, each cell is modified by applying the rules.

View file

@ -72,9 +72,10 @@ li.nav-item a:active { background: gray; color: white; }
} }
.widget { .widget {
margin: 0; background-color: silver;
padding: 0.25em 1em;
border: thin solid white; border: thin solid white;
margin-top: 0;
margin-bottom: 0;
} }
.world { .world {
@ -86,8 +87,6 @@ div.error {
} }
form { form {
width: 100%;
background-color: silver;
border: thin solid silver; border: thin solid silver;
} }
@ -100,7 +99,7 @@ h1, h2, h3, h4, h5 {
color: white; color: white;
} }
p, pre, ul, ol, dl, menu, h1, h2, h3, h4, h5 { div.content, form, p, pre, ul, ol, dl, menu, h1, h2, h3, h4, h5 {
padding: 0.25em 10%; padding: 0.25em 10%;
} }
@ -118,15 +117,8 @@ input.required:after {
} }
label { label {
min-width: 35%; width: 30em;
} min-width: 20em;
label, input {
padding: 0.25em 1em;
margin: 0 0.5em;
}
label {
border-right: thin solid gray; border-right: thin solid gray;
} }
@ -138,9 +130,19 @@ menu li::before {
content: "|| "; content: "|| ";
} }
div.world table, div.world tr td { div.world table, div.world table tr td {
padding: 0; padding: 0;
margin: 0; margin: 0;
border-collapse: collapse;
border: none; border: none;
} }
table.music-ruled tr:nth-child(odd) {
background-color: silver;
}
th, td {
text-align: left;
padding: 0 0.25em;
}

View file

@ -3441,7 +3441,30 @@ important.</p>
([world cell depth state] ([world cell depth state]
(get-neighbours-with-state world (:x cell) (:y cell) depth state)) (get-neighbours-with-state world (:x cell) (:y cell) depth state))
([world cell state] ([world cell state]
(get-neighbours-with-state world cell 1 state)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-engine.world" name="mw-engine.world"><h1 class="project-name">mw-engine.world</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>Functions to create and to print two dimensional cellular automata. Nothing in this (get-neighbours-with-state world cell 1 state)))</pre></td></tr><tr><td class="docs"><p>If this <code>cell</code>s x and y properties are equal to these <code>x</code> and <code>y</code> values,
return a cell like this cell but with the value of this <code>property</code> set to
this <code>value</code>. Otherwise, just return this <code>cell</code>.</p>
</td><td class="codes"><pre class="brush: clojure">(defn- set-cell-property
[cell x y property value]
(cond
(and (= x (:x cell)) (= y (:y cell)))
(merge cell {property value})
true
cell))</pre></td></tr><tr><td class="docs"><p>Return a world like this <code>world</code> but with the value of exactly one <code>property</code>
of one <code>cell</code> changed to this <code>value</code></p>
</td><td class="codes"><pre class="brush: clojure">(defn set-property
([world cell property value]
(set-property world (:x cell) (:y cell) property value))
([world x y property value]
(apply
vector ;; we want a vector of vectors, not a list of lists, for efficiency
(map
(fn [row]
(apply
vector
(map #(set-cell-property % x y property value)
row)))
world))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-engine.world" name="mw-engine.world"><h1 class="project-name">mw-engine.world</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>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 file should determine what states are possible within the automaton, except for the
initial state, :new.</p> initial state, :new.</p>

View file

@ -3126,6 +3126,7 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-engine.natural-rules :as rules] [mw-engine.natural-rules :as rules]
[mw-parser.bulk :as compiler] [mw-parser.bulk :as compiler]
[hiccup.core :refer [html]] [hiccup.core :refer [html]]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs"> [noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn format-css-class [statekey] </td><td class="codes"><pre class="brush: clojure">(defn format-css-class [statekey]
&quot;Format this statekey, assumed to be a keyword indicating a state in the &quot;Format this statekey, assumed to be a keyword indicating a state in the
@ -3141,7 +3142,7 @@ net.brehaut.ClojureTools = (function (SH) {
[cell] [cell]
(let [state (:state cell)] (let [state (:state cell)]
[:td {:class (format-css-class state) :title (format-mouseover cell)} [:td {:class (format-css-class state) :title (format-mouseover cell)}
[:a {:href (format &quot;inspect?x=%d&amp;amp;y=%d&quot; (:x cell) (:y cell))} [:a {:href (format &quot;inspect?x=%d&amp;y=%d&quot; (:x cell) (:y cell))}
[:img {:alt (:state cell) :src (format-image-path state)}]]]))</pre></td></tr><tr><td class="docs"><p>Render this world row as a Hiccup table row.</p> [:img {:alt (:state cell) :src (format-image-path state)}]]]))</pre></td></tr><tr><td class="docs"><p>Render this world row as a Hiccup table row.</p>
</td><td class="codes"><pre class="brush: clojure">(defn render-world-row </td><td class="codes"><pre class="brush: clojure">(defn render-world-row
[row] [row]
@ -3151,11 +3152,13 @@ net.brehaut.ClojureTools = (function (SH) {
(let [world (or (session/get :world) (let [world (or (session/get :world)
(engine/transform-world (engine/transform-world
(heightmap/apply-heightmap (heightmap/apply-heightmap
&quot;resources/public/img/heightmaps/small_hill.png&quot; (io/get-resource &quot;/img/heightmaps/small_hill.png&quot;)
;; &quot;resources/public/img/heightmaps/great_britain_and_ireland_small.png&quot;) ;; &quot;resources/public/img/heightmaps/great_britain_and_ireland_small.png&quot;)
rules/init-rules)) rules/init-rules))
rules (or (session/get :rules) rules (or (session/get :rules)
(do (session/put! :rules (compiler/compile-file &quot;resources/rulesets/basic.txt&quot;)) (do (session/put! :rules
(compiler/compile-file
(io/get-resource &quot;/rulesets/basic.txt&quot;)))
(session/get :rules))) (session/get :rules)))
generation (+ (or (session/get :generation) 0) 1) generation (+ (or (session/get :generation) 0) 1)
w2 (engine/transform-world world rules) w2 (engine/transform-world world rules)
@ -3166,22 +3169,17 @@ net.brehaut.ClojureTools = (function (SH) {
(apply vector (apply vector
(cons :table (cons :table
(map render-world-row w2))) (map render-world-row w2)))
[:p (str &quot;Generation &quot; generation)]]))</pre></td></tr><tr><td class="docs"><p>Render the world implied by the session as a complete HTML page.</p> [:p (str &quot;Generation &quot; generation)]]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn render-world </td><td class="codes"><pre class="brush: clojure">(defn render-inspector
[] [cell table]
(html [:table {:class &quot;music-ruled&quot;}
[:html [:tr
[:head [:td {:colspan 2 :style &quot;text-align: center;&quot;}
[:title &quot;MicroWorld demo&quot;] [:img {:src (str &quot;img/tiles/&quot; (name (:state cell)) &quot;.png&quot;)
[:link {:media &quot;only screen and (max-device-width: 480px)&quot; :href &quot;css/phone.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}] :width 64
[:link {:media &quot;only screen and (min-device-width: 481px) and (max-device-width: 1024px)&quot; :href &quot;css/tablet.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}] :height 64}]]]
[:link {:media &quot;screen and (min-device-width: 1025px)&quot; :href &quot;css/standard.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}] [:tr [:th &quot;Key&quot;][:th &quot;Value&quot;]]
[:link {:media &quot;print&quot; :href &quot;css/print.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}] (map #(vector :tr (vector :th %)(vector :td (cell %))) (keys cell))])</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.repl" name="mw-ui.repl"><h1 class="project-name">mw-ui.repl</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
[:link {:href &quot;css/states.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[:meta {:http-equiv &quot;refresh&quot; :content &quot;5&quot;}]]
[:body
(render-world-table)
]]))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.repl" name="mw-ui.repl"><h1 class="project-name">mw-ui.repl</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.repl </td><td class="codes"><pre class="brush: clojure">(ns mw-ui.repl
(:use mw-ui.handler (:use mw-ui.handler
ring.server.standalone ring.server.standalone
@ -3214,16 +3212,40 @@ net.brehaut.ClojureTools = (function (SH) {
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.routes.home </td><td class="codes"><pre class="brush: clojure">(ns mw-ui.routes.home
(:use clojure.walk (:use clojure.walk
compojure.core compojure.core
[mw-engine.utils :as engine-utils]
[mw-ui.routes.rules :as rules] [mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params]) [mw-ui.routes.params :as params])
(:require [hiccup.core :refer [html]] (:require [hiccup.core :refer [html]]
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.util :as util] [mw-ui.util :as util]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
[noir.session :as session]))</pre></td></tr><tr><td class="docs"> [noir.session :as session]
[ring.util.response :as response]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn home-page [] </td><td class="codes"><pre class="brush: clojure">(defn home-page []
(layout/render &quot;trusted-content.html&quot; {:title &quot;Welcome to MicroWorld&quot; (layout/render &quot;trusted-content.html&quot; {:title &quot;Welcome to MicroWorld&quot;
:content (util/md-&gt;html &quot;/md/mw-ui.md&quot;)}))</pre></td></tr><tr><td class="docs"> :content (util/md-&gt;html &quot;/md/mw-ui.md&quot;)}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn inspect-page [request]
(let [params (keywordize-keys (:params request))
xs (:x params)
ys (:y params)
x (if (not (empty? xs)) (read-string xs) 0)
y (if (not (empty? ys)) (read-string ys) 0)
world (session/get :world)
cell (engine-utils/get-cell world x y)
state (:state params)]
(cond state
(do
(session/put! :world (engine-utils/set-property world cell :state (keyword state)))
(response/redirect &quot;world&quot;))
true
(layout/render &quot;inspector.html&quot;
{:title (format &quot;Inspect cell at %d, %d&quot; x y)
:content (html (world/render-inspector cell world))
:cell cell
:x (:x cell)
:y (:y cell)
:states (util/list-resources
&quot;/img/tiles&quot; #&quot;([0-9a-z-_]+).png&quot;)}))))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn world-page [] </td><td class="codes"><pre class="brush: clojure">(defn world-page []
(layout/render &quot;trusted-content.html&quot; (layout/render &quot;trusted-content.html&quot;
{:title &quot;Watch your world grow&quot; {:title &quot;Watch your world grow&quot;
@ -3250,8 +3272,8 @@ net.brehaut.ClojureTools = (function (SH) {
</td><td class="codes"><pre class="brush: clojure">(defn docs-page [] </td><td class="codes"><pre class="brush: clojure">(defn docs-page []
(layout/render &quot;docs.html&quot; {:title &quot;Documentation&quot; (layout/render &quot;docs.html&quot; {:title &quot;Documentation&quot;
:parser (util/md-&gt;html &quot;/md/mw-parser.md&quot; ) :parser (util/md-&gt;html &quot;/md/mw-parser.md&quot; )
:states (util/list-resources &quot;resources/public/img/tiles&quot; #&quot;([0-9a-z-_]+).png&quot;) :states (util/list-resources &quot;/img/tiles&quot; #&quot;([0-9a-z-_]+).png&quot;)
:lessons (util/list-resources &quot;resources/public/md/lesson-plans&quot; #&quot;([0-9a-z-_]+).md&quot;) :lessons (util/list-resources &quot;/md/lesson-plans&quot; #&quot;([0-9a-z-_]+).md&quot;)
:components [&quot;mw-engine&quot; &quot;mw-parser&quot; &quot;mw-ui&quot;]}))</pre></td></tr><tr><td class="docs"> :components [&quot;mw-engine&quot; &quot;mw-parser&quot; &quot;mw-ui&quot;]}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defroutes home-routes </td><td class="codes"><pre class="brush: clojure">(defroutes home-routes
(GET &quot;/&quot; [] (home-page)) (GET &quot;/&quot; [] (home-page))
@ -3262,9 +3284,12 @@ net.brehaut.ClojureTools = (function (SH) {
(GET &quot;/md&quot; request (md-page request)) (GET &quot;/md&quot; request (md-page request))
(POST &quot;/params&quot; request (params/params-page request)) (POST &quot;/params&quot; request (params/params-page request))
(GET &quot;/rules&quot; request (rules/rules-page request)) (GET &quot;/rules&quot; request (rules/rules-page request))
(POST &quot;/rules&quot; request (rules/rules-page request)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.routes.params" name="mw-ui.routes.params"><h1 class="project-name">mw-ui.routes.params</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"> (POST &quot;/rules&quot; request (rules/rules-page request))
(GET &quot;/inspect&quot; request (inspect-page request))
(POST &quot;/inspect&quot; request (inspect-page request)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.routes.params" name="mw-ui.routes.params"><h1 class="project-name">mw-ui.routes.params</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.routes.params </td><td class="codes"><pre class="brush: clojure">(ns mw-ui.routes.params
(:use clojure.walk (:use clojure.walk
clojure.java.io
compojure.core) compojure.core)
(:require [hiccup.core :refer [html]] (:require [hiccup.core :refer [html]]
[mw-engine.heightmap :as heightmap] [mw-engine.heightmap :as heightmap]
@ -3272,12 +3297,13 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.util :as util] [mw-ui.util :as util]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs"> [noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn- send-params [] </td><td class="codes"><pre class="brush: clojure">(defn- send-params []
{:title &quot;Choose your world&quot; {:title &quot;Choose your world&quot;
:heightmaps (util/list-resources &quot;resources/public/img/heightmaps&quot; #&quot;([0-9a-z-_]+).png&quot;) :heightmaps (util/list-resources &quot;/img/heightmaps&quot; #&quot;([0-9a-z-_]+).png&quot;)
:pause (or (session/get :pause) 5) :pause (or (session/get :pause) 5)
:rulesets (util/list-resources &quot;resources/rulesets&quot; #&quot;([0-9a-z-_]+).txt&quot;) :rulesets (util/list-resources &quot;/rulesets&quot; #&quot;([0-9a-z-_]+).txt&quot;)
})</pre></td></tr><tr><td class="docs"><p>Handler for params request. If no <code>request</code> passed, show empty params form. })</pre></td></tr><tr><td class="docs"><p>Handler for params request. If no <code>request</code> passed, show empty params form.
If <code>request</code> is passed, put parameters from request into session and show If <code>request</code> is passed, put parameters from request into session and show
the world page.</p> the world page.</p>
@ -3290,15 +3316,15 @@ net.brehaut.ClojureTools = (function (SH) {
map (:heightmap params) map (:heightmap params)
pause (:pause params) pause (:pause params)
rulefile (:ruleset params) rulefile (:ruleset params)
rulepath (str &quot;resources/rulesets/&quot; rulefile &quot;.txt&quot;)] rulepath (str &quot;/rulesets/&quot; rulefile &quot;.txt&quot;)]
(if (not (= map &quot;&quot;)) (if (not (= map &quot;&quot;))
(session/put! :world (session/put! :world
(heightmap/apply-heightmap (heightmap/apply-heightmap
(str &quot;resources/public/img/heightmaps/&quot; map &quot;.png&quot;)))) (io/get-resource (str &quot;/img/heightmaps/&quot; map &quot;.png&quot;)))))
(if (not (= rulefile &quot;&quot;)) (if (not (= rulefile &quot;&quot;))
(do (do
(session/put! :rule-text (slurp rulepath)) (session/put! :rule-text (io/slurp-resource rulepath))
(session/put! :rules (compiler/compile-file rulepath)))) (session/put! :rules (compiler/compile-file (io/get-resource rulepath)))))
(if (not (= pause &quot;&quot;)) (if (not (= pause &quot;&quot;))
(session/put! :pause pause)) (session/put! :pause pause))
(layout/render &quot;params.html&quot; (layout/render &quot;params.html&quot;
@ -3323,6 +3349,7 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.util :as util] [mw-ui.util :as util]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs"> [noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn process-rules-request </td><td class="codes"><pre class="brush: clojure">(defn process-rules-request
[request] [request]
@ -3337,7 +3364,7 @@ net.brehaut.ClojureTools = (function (SH) {
&quot; rules&quot;) }) &quot; rules&quot;) })
true {:rule-text (or true {:rule-text (or
(session/get :rule-text) (session/get :rule-text)
(slurp &quot;resources/rulesets/basic.txt&quot;)) (io/slurp-resource &quot;/rulesets/basic.txt&quot;))
:message &quot;No rules found in request; loading defaults&quot;}) :message &quot;No rules found in request; loading defaults&quot;})
(catch Exception e (catch Exception e
{:rule-text src {:rule-text src
@ -3362,6 +3389,7 @@ net.brehaut.ClojureTools = (function (SH) {
(rules-page nil)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.util" name="mw-ui.util"><h1 class="project-name">mw-ui.util</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"> (rules-page nil)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.util" name="mw-ui.util"><h1 class="project-name">mw-ui.util</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.util </td><td class="codes"><pre class="brush: clojure">(ns mw-ui.util
(:require [noir.io :as io] (:require [noir.io :as io]
[noir.session :as session]
[markdown.core :as md]))</pre></td></tr><tr><td class="docs"><p>reads a markdown file from public/md and returns an HTML string</p> [markdown.core :as md]))</pre></td></tr><tr><td class="docs"><p>reads a markdown file from public/md and returns an HTML string</p>
</td><td class="codes"><pre class="brush: clojure">(defn md-&gt;html </td><td class="codes"><pre class="brush: clojure">(defn md-&gt;html
[filename] [filename]
@ -3370,8 +3398,11 @@ net.brehaut.ClojureTools = (function (SH) {
(md/md-to-html-string)))</pre></td></tr><tr><td class="docs"> (md/md-to-html-string)))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn list-resources [directory pattern] </td><td class="codes"><pre class="brush: clojure">(defn list-resources [directory pattern]
&quot;List resource files matching `pattern` in `directory`.&quot; &quot;List resource files matching `pattern` in `directory`.&quot;
(let
[path (str (io/resource-path) directory)]
(session/put! :list-resources-path path)
(sort (sort
(filter #(not (nil? %)) (filter #(not (nil? %))
(map #(first (rest (re-matches pattern (.getName %)))) (map #(first (rest (re-matches pattern (.getName %))))
(file-seq (clojure.java.io/file directory))))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/fogus/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false; (file-seq (clojure.java.io/file path)))))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/fogus/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.all()</script></body></html> SyntaxHighlighter.all()</script></body></html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 192 B

View file

@ -15,7 +15,10 @@ if state is in grassland or heath and more than 2 neighbours are pasture then st
if state is pasture and more than 3 neighbours are pasture and fewer than 1 neighbours are camp and fewer than 1 neighbours within 2 are house then state should be camp if state is pasture and more than 3 neighbours are pasture and fewer than 1 neighbours are camp and fewer than 1 neighbours within 2 are house then state should be camp
;; the idea of agriculture spreads ;; the idea of agriculture spreads
if state is in grassland or heath and some neighbours are pasture and some neighbours within 3 are house then state should be pasture if state is in grassland or heath and some neighbours within 3 are house then state should be pasture
;; nomads don't move on while the have crops growing. That would be silly!
if state is camp and some neighbours are ploughland then state should be camp
;; nomads move on ;; nomads move on
if state is camp then 1 chance in 5 state should be waste if state is camp then 1 chance in 5 state should be waste
@ -82,8 +85,8 @@ if state is forest and fertility is more than 5 and altitude is less than 70 the
if state is climax then 1 chance in 500 state should be fire if state is climax then 1 chance in 500 state should be fire
;; Climax forest neighbouring fires is likely to catch fire. So are buildings. ;; Forest neighbouring fires is likely to catch fire. So are buildings.
if state is in climax or camp or house or inn and some neighbours are fire then 1 chance in 3 state should be fire if state is in forest or climax or camp or house or inn and some neighbours are fire then 1 chance in 3 state should be fire
;; Climax forest near to settlement may be cleared for timber ;; Climax forest near to settlement may be cleared for timber
if state is in climax and more than 3 neighbours within 2 are house then state should be scrub if state is in climax and more than 3 neighbours within 2 are house then state should be scrub
@ -123,4 +126,3 @@ if state is new and altitude is more than 200 then state should be snow
;; otherwise, we have grassland. ;; otherwise, we have grassland.
if state is new then state should be grassland if state is new then state should be grassland

View file

@ -93,12 +93,15 @@
user interface is a web browser. It would be possible to arrange a user interface is a web browser. It would be possible to arrange a
classroom with one copy of MicroWorld on a single server, and each child's classroom with one copy of MicroWorld on a single server, and each child's
machine running MicroWorld from that single server.</p> machine running MicroWorld from that single server.</p>
<p>However, performance isn't very good, and unless you have an unusually <p>However, many users accessing the same server at the same time may
powerful server you may find that when a full class of pupils are running lead to poor performance.
MicroWorld from a single server performance may be frustratingly poor. Check performance on your system before introducing a class to it, and if in doubt,
Check your performance before introducing a class to it, and if in doubt,
running a separate copy on each machine used by children may well be more running a separate copy on each machine used by children may well be more
satisfactory.</p> satisfactory.</p>
<p>If many users are using the same shared machine, you should make sure
that they don't use the 'original' or 'med' versions of the Great Britain
and Ireland map - both of these are big, and performance will inevitably
be poor.</p>
<h3>Subject areas</h3> <h3>Subject areas</h3>
<p>One of my main objectives in writing MicroWorld was to create a system <p>One of my main objectives in writing MicroWorld was to create a system
@ -148,15 +151,34 @@
class projects. Writing rules will enable discussion of why castles, or class projects. Writing rules will enable discussion of why castles, or
mills, are positioned where they are, and what the social consequences of mills, are positioned where they are, and what the social consequences of
these developments are.</p> these developments are.</p>
<p>You might also want to explore the conditions for the spread of epidemic
disease - such as the black death - I've provided a state for this,
but no rules.</p>
<h4>IT/Informatics</h4> <h4>IT/Informatics</h4>
<p>Obviously, any of the rulesets but particularly the <em>gameoflife</em> <p>Obviously, any of the rulesets but particularly the <em>life</em>
ruleset are good introduction points to informatics lessons. The rule ruleset are good introduction points to informatics lessons. The rule
language is sufficiently simple that introducing children to writing language is sufficiently simple that introducing children to writing
their own rules can begin almost as soon as basic literacy is their own rules can begin almost as soon as basic literacy is
established.</p> established.</p>
<p>In more advanced IT lessons, at the upper end of primary school or in <p>In more advanced IT lessons, at the upper end of primary school or in
secondary schools, I would encourage you to explore modifying the engine secondary schools, I would encourage you to explore modifying the engine
itself in your classes.</p> itself in your classes. Also, it would be interesting to write an
export program which would export MicroWorld maps to Minecraft, or
render them as explorable three dimensional spaces using
<a href="http://jmonkeyengine.org/">JMonkeyEngine</a>
or <a href="https://nightmod.net/">NightMod</a>.</p>
<h4>Art and design</h4>
<p>A number of projects, progressively more ambitious, are possible in
art and design.</p>
<ol>
<li>The tiles I've drawn are pretty basic - again, that's
intentional, children can easily produce better ones. They don't have to
be 32x32, but they do all have to be the same size.</li>
<li>The stylesheets providing the overall look and feel of the system
could be modified</li>
<li>If you have an IT project to render a 3d world, you will need 3d
models of each of the states, instead of tiles. That might be a job for
<a href="http://blender.org">Blender</a>.</li></ol>
<h3>Lesson plans</h3> <h3>Lesson plans</h3>
<ul> <ul>

View file

@ -28,7 +28,7 @@
[cell] [cell]
(let [state (:state cell)] (let [state (:state cell)]
[:td {:class (format-css-class state) :title (format-mouseover cell)} [:td {:class (format-css-class state) :title (format-mouseover cell)}
[:a {:href (format "inspect?x=%d&amp;y=%d" (:x cell) (:y cell))} [:a {:href (format "inspect?x=%d&y=%d" (:x cell) (:y cell))}
[:img {:alt (:state cell) :src (format-image-path state)}]]])) [:img {:alt (:state cell) :src (format-image-path state)}]]]))
(defn render-world-row (defn render-world-row
@ -63,19 +63,16 @@
(map render-world-row w2))) (map render-world-row w2)))
[:p (str "Generation " generation)]])) [:p (str "Generation " generation)]]))
(defn render-world (defn render-inspector
"Render the world implied by the session as a complete HTML page." [cell table]
[] [:table {:class "music-ruled"}
(html [:tr
[:html [:td {:colspan 2 :style "text-align: center;"}
[:head [:img {:src (str "img/tiles/" (name (:state cell)) ".png")
[:title "MicroWorld demo"] :width 64
[:link {:media "only screen and (max-device-width: 480px)" :href "css/phone.css" :type "text/css" :rel "stylesheet"}] :height 64}]]]
[:link {:media "only screen and (min-device-width: 481px) and (max-device-width: 1024px)" :href "css/tablet.css" :type "text/css" :rel "stylesheet"}] [:tr [:th "Key"][:th "Value"]]
[:link {:media "screen and (min-device-width: 1025px)" :href "css/standard.css" :type "text/css" :rel "stylesheet"}] (map #(vector :tr (vector :th %)(vector :td (cell %))) (keys cell))])
[:link {:media "print" :href "css/print.css" :type "text/css" :rel "stylesheet"}]
[:link {:href "css/states.css" :type "text/css" :rel "stylesheet"}]
[:meta {:http-equiv "refresh" :content "5"}]]
[:body
(render-world-table)
]]))

View file

@ -1,18 +1,43 @@
(ns mw-ui.routes.home (ns mw-ui.routes.home
(:use clojure.walk (:use clojure.walk
compojure.core compojure.core
[mw-engine.utils :as engine-utils]
[mw-ui.routes.rules :as rules] [mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params]) [mw-ui.routes.params :as params])
(:require [hiccup.core :refer [html]] (:require [hiccup.core :refer [html]]
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.util :as util] [mw-ui.util :as util]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
[noir.session :as session])) [noir.session :as session]
[ring.util.response :as response]))
(defn home-page [] (defn home-page []
(layout/render "trusted-content.html" {:title "Welcome to MicroWorld" (layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
:content (util/md->html "/md/mw-ui.md")})) :content (util/md->html "/md/mw-ui.md")}))
(defn inspect-page [request]
(let [params (keywordize-keys (:params request))
xs (:x params)
ys (:y params)
x (if (not (empty? xs)) (read-string xs) 0)
y (if (not (empty? ys)) (read-string ys) 0)
world (session/get :world)
cell (engine-utils/get-cell world x y)
state (:state params)]
(cond state
(do
(session/put! :world (engine-utils/set-property world cell :state (keyword state)))
(response/redirect "world"))
true
(layout/render "inspector.html"
{:title (format "Inspect cell at %d, %d" x y)
:content (html (world/render-inspector cell world))
:cell cell
:x (:x cell)
:y (:y cell)
:states (util/list-resources
"/img/tiles" #"([0-9a-z-_]+).png")}))))
(defn world-page [] (defn world-page []
(layout/render "trusted-content.html" (layout/render "trusted-content.html"
{:title "Watch your world grow" {:title "Watch your world grow"
@ -43,8 +68,8 @@
(defn docs-page [] (defn docs-page []
(layout/render "docs.html" {:title "Documentation" (layout/render "docs.html" {:title "Documentation"
:parser (util/md->html "/md/mw-parser.md" ) :parser (util/md->html "/md/mw-parser.md" )
:states (util/list-resources "resources/public/img/tiles" #"([0-9a-z-_]+).png") :states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png")
:lessons (util/list-resources "resources/public/md/lesson-plans" #"([0-9a-z-_]+).md") :lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md")
:components ["mw-engine" "mw-parser" "mw-ui"]})) :components ["mw-engine" "mw-parser" "mw-ui"]}))
(defroutes home-routes (defroutes home-routes
@ -56,4 +81,7 @@
(GET "/md" request (md-page request)) (GET "/md" request (md-page request))
(POST "/params" request (params/params-page request)) (POST "/params" request (params/params-page request))
(GET "/rules" request (rules/rules-page request)) (GET "/rules" request (rules/rules-page request))
(POST "/rules" request (rules/rules-page request))) (POST "/rules" request (rules/rules-page request))
(GET "/inspect" request (inspect-page request))
(POST "/inspect" request (inspect-page request))
)

View file

@ -6,8 +6,8 @@
;; Test file specifically to test the helper function in rules handler ;; Test file specifically to test the helper function in rules handler
(deftest test-rules-processor (deftest test-rules-processor
(testing "Rules processor" (testing "Rules processor"
(let [request {:src "if state is new and altitude is less than 10 then state should be water"} (let [request {:form-params {:src "if state is new and altitude is less than 10 then state should be water"}}
response (process-rules-request request)] response (process-rules-request request)]
(is (= (:message response) "Successfully compiled 1 rules")) (is (= (:message response) "Successfully compiled 1 rules"))
(is (= (count (:rules response)) 1)) (is (= (count (:rules response)) 1))
(is (= (:rule-text response) (:src request)))))) (is (= (:rule-text response) (:src (:form-params request)))))))