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

@ -72,9 +72,10 @@ li.nav-item a:active { background: gray; color: white; }
}
.widget {
margin: 0;
padding: 0.25em 1em;
border: thin solid white;
background-color: silver;
border: thin solid white;
margin-top: 0;
margin-bottom: 0;
}
.world {
@ -86,8 +87,6 @@ div.error {
}
form {
width: 100%;
background-color: silver;
border: thin solid silver;
}
@ -100,7 +99,7 @@ h1, h2, h3, h4, h5 {
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%;
}
@ -118,15 +117,8 @@ input.required:after {
}
label {
min-width: 35%;
}
label, input {
padding: 0.25em 1em;
margin: 0 0.5em;
}
label {
width: 30em;
min-width: 20em;
border-right: thin solid gray;
}
@ -138,9 +130,19 @@ menu li::before {
content: "|| ";
}
div.world table, div.world tr td {
div.world table, div.world table tr td {
padding: 0;
margin: 0;
border-collapse: collapse;
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]
(get-neighbours-with-state world (:x cell) (:y cell) depth 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
initial state, :new.</p>

View file

@ -3126,6 +3126,7 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-engine.natural-rules :as rules]
[mw-parser.bulk :as compiler]
[hiccup.core :refer [html]]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
</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
@ -3141,7 +3142,7 @@ net.brehaut.ClojureTools = (function (SH) {
[cell]
(let [state (:state 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>
</td><td class="codes"><pre class="brush: clojure">(defn render-world-row
[row]
@ -3151,11 +3152,13 @@ net.brehaut.ClojureTools = (function (SH) {
(let [world (or (session/get :world)
(engine/transform-world
(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;)
rules/init-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)))
generation (+ (or (session/get :generation) 0) 1)
w2 (engine/transform-world world rules)
@ -3166,22 +3169,17 @@ net.brehaut.ClojureTools = (function (SH) {
(apply vector
(cons :table
(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>
</td><td class="codes"><pre class="brush: clojure">(defn render-world
[]
(html
[:html
[:head
[:title &quot;MicroWorld demo&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;}]
[: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;}]
[: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;}]
[:link {:media &quot;print&quot; :href &quot;css/print.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[: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">
[:p (str &quot;Generation &quot; generation)]]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn render-inspector
[cell table]
[:table {:class &quot;music-ruled&quot;}
[:tr
[:td {:colspan 2 :style &quot;text-align: center;&quot;}
[:img {:src (str &quot;img/tiles/&quot; (name (:state cell)) &quot;.png&quot;)
:width 64
:height 64}]]]
[:tr [:th &quot;Key&quot;][:th &quot;Value&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">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.repl
(:use mw-ui.handler
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
(:use clojure.walk
compojure.core
[mw-engine.utils :as engine-utils]
[mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params])
(:require [hiccup.core :refer [html]]
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[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 []
(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">
</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 []
(layout/render &quot;trusted-content.html&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 []
(layout/render &quot;docs.html&quot; {:title &quot;Documentation&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;)
:lessons (util/list-resources &quot;resources/public/md/lesson-plans&quot; #&quot;([0-9a-z-_]+).md&quot;)
:states (util/list-resources &quot;/img/tiles&quot; #&quot;([0-9a-z-_]+).png&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">
</td><td class="codes"><pre class="brush: clojure">(defroutes home-routes
(GET &quot;/&quot; [] (home-page))
@ -3262,9 +3284,12 @@ net.brehaut.ClojureTools = (function (SH) {
(GET &quot;/md&quot; request (md-page request))
(POST &quot;/params&quot; request (params/params-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
(:use clojure.walk
clojure.java.io
compojure.core)
(:require [hiccup.core :refer [html]]
[mw-engine.heightmap :as heightmap]
@ -3272,12 +3297,13 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn- send-params []
{: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)
: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.
If <code>request</code> is passed, put parameters from request into session and show
the world page.</p>
@ -3290,15 +3316,15 @@ net.brehaut.ClojureTools = (function (SH) {
map (:heightmap params)
pause (:pause 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;))
(session/put! :world
(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;))
(do
(session/put! :rule-text (slurp rulepath))
(session/put! :rules (compiler/compile-file rulepath))))
(session/put! :rule-text (io/slurp-resource rulepath))
(session/put! :rules (compiler/compile-file (io/get-resource rulepath)))))
(if (not (= pause &quot;&quot;))
(session/put! :pause pause))
(layout/render &quot;params.html&quot;
@ -3323,6 +3349,7 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn process-rules-request
[request]
@ -3337,7 +3364,7 @@ net.brehaut.ClojureTools = (function (SH) {
&quot; rules&quot;) })
true {:rule-text (or
(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;})
(catch Exception e
{: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">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.util
(: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>
</td><td class="codes"><pre class="brush: clojure">(defn md-&gt;html
[filename]
@ -3370,8 +3398,11 @@ net.brehaut.ClojureTools = (function (SH) {
(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]
&quot;List resource files matching `pattern` in `directory`.&quot;
(sort
(filter #(not (nil? %))
(let
[path (str (io/resource-path) directory)]
(session/put! :list-resources-path path)
(sort
(filter #(not (nil? %))
(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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 192 B

Before After
Before After

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
;; 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
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
;; Climax 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
;; Forest neighbouring fires is likely to catch fire. So are buildings.
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
if state is in climax and more than 3 neighbours within 2 are house then state should be scrub
@ -122,5 +125,4 @@ if state is new and altitude is less than 10 then state should be water
if state is new and altitude is more than 200 then state should be snow
;; otherwise, we have grassland.
if state is new then state should be grassland
if state is new then state should be grassland