Restyling; much reorganisation of documentation.

This commit is contained in:
Simon Brooke 2014-07-23 10:04:04 +01:00
parent 05e9daf662
commit c15cd08159
17 changed files with 217 additions and 257 deletions

View file

@ -88,6 +88,9 @@ all those:
I'll leave you to work out what the rules of life are for yourself, from the
Wiki page I linked to.
**CHEAT** _You'll find other rule sets you can explore if you go to the_
_[Parameters](params) page_.
### Change the engine
If you want to modify the engine itself, you will need
@ -131,6 +134,19 @@ which is quite small and will run on a Raspberry Pi, or
[LightTable](http://www.lighttable.com/), which is extremely helpful but needs
a more powerful computer.
#### Worthwhile projects
If you would like to work on the engine, there's things that would be worth
improving:
1. Better arithmetic in actions
2. Better arithmetic in conditions - it would be useful to be able to say _'if generation is more than 64 - y then state should be snow'_. This would make the ice retreat in the right direction in the iceage rule set.
3. Better error messages when rules don't parse, explaining where the problem occured _(very hard)_.
4. Make this all work in ClojureScript in the browser, so there's less load on the server and one server can support more users _(quite hard)_.
5. Optimisation: MicroWorld runs quite slowly, you can't really do big maps and one server won't support many users. There must be many ways performance can be improved.
If you make changes which you think improve MicroWorld, please [mail them to me](mailto:simon@journeyman.cc).
Have fun!
## License

View file

@ -14,7 +14,7 @@
[noir-exception "0.2.2"]]
:repl-options {:init-ns mw-ui.repl}
:plugins [[lein-ring "0.8.10"]
:plugins [[lein-ring "0.8.11"]
[lein-environ "0.5.0"]
[lein-marginalia "0.7.1"]]
:ring {:handler mw-ui.handler/app

View file

@ -1,94 +0,0 @@
.form-all{list-style:none;list-style-position:outside;margin:0px;font-family:Verdana;font-size:12px}.form-captcha{border:1px
solid #ccc;background:#f5f5f5;padding:6px;width:152px;-moz-border-radius:4px 4px 4px 4px;-webkit-border-radius:4px;border-radius:4px 4px 4px 4px}#payment_total{display:inline-block}#coupon-message{font-size:10px;font-weight:normal;white-space:normal}.form-captcha:hover{border:1px
solid #aaa}.form-captcha-image{border:1px
solid #aaa;-moz-border-radius:4px 4px 4px 4px;-webkit-border-radius:4px;border-radius:4px 4px 4px 4px}.form-collapse-table{height:58px;border:1px
solid #ccc;background:#f5f5f5 url(/images/soft-grad.png) repeat-x;position:relative}.form-list{padding:3px;border:1px
solid #CCC;-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.2) inset;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.2) inset;box-shadow:0 1px 1px rgba(0, 0, 0, 0.2) inset}.form-list
option{padding:2px}.form-list option:nth-child(2n+1){background:#f5f5f5}.form-textarea{font-family:"Lucida Grande",Verdana}.form-textarea-limit{}.form-textarea-limit>span{display:inline-block}.form-textarea-limit
textarea{overflow:auto}.form-textarea-limit textarea:focus{outline:none !important}.form-textarea-limit-indicator{color:#666;font-size:9px;margin-top: -1px;padding:2px;text-align:right}.form-textarea-limit-indicator-error{background:#FAA;color:#fff}.nicEdit-main{background-color:white}.form-datetime-validation-error{background:#FAA;color:#fff}.form-collapse-left{}.form-collapse-mid{text-shadow:0px 2px 0px #fff;float:left;font-size:18px;margin:16px
45px 16px 20px}.form-product-item{display:inline-block;padding:5px
5px 5px 10px;position:relative}.form-product-item
img{display:block;position:static;margin:0
12px 0 0;float:left;-moz-border-radius:3px 3px;-webkit-border-radius:3px 3px;border-radius:3px 3px}.hover-product-item:hover{background:#f5f5f5;color:#000}.form-product-item label, .form-product-item .form-radio, .form-product-item .form-checkbox{cursor:pointer}.form-special-subtotal{display:block;font-size:10px;margin-left:10px;margin-top:6px}.form-product-image,.form-product-image-with-options{margin:5px;margin-left:10px}.form-product-image-with-options{position:absolute;top:15px;-moz-border-radius:5px 5px;-webkit-border-radius:5px 5px;border-radius:5px 5px}.form-radio,.form-checkbox{vertical-align:middle;margin:0px;padding:0px}.form-radio-item,.form-checkbox-item{margin-top:5px;float:left}.form-multiple-column,.form-single-column{display:inline-block}.form-multiple-column .form-radio-item, .form-multiple-column .form-checkbox-item{width:150px}.form-radio-item label, .form-checkbox-item
label{margin-left:5px}.form-radio-item br, .form-checkbox-item
br{clear:left}.form-submit-button,.form-submit-reset,.form-submit-print,.form-screen-button{margin:0px;overflow:visible;padding:1px
6px;width:auto}.form-submit-button::-moz-focus-inner,.form-submit-reset::-moz-focus-inner{border:0px;padding:1px
6px}.form-button-red{border:1px
solid red}.form-button-magenta{border:1px
solid magenta}.form-screen-message{width:260px;height:100px}.form-screen-button
div{background-image:url("/images/photo.png");background-position:center;background-repeat:no-repeat;height:50px;width:50px}.form-screen-button{position:absolute;top:1px;margin:0px;margin-left:10px;padding:0px;background:#fdc000;background: -moz-linear-gradient(top, #fdc000 0%, #fe8900 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fdc000), color-stop(100%,#fe8900));background: -webkit-linear-gradient(top, #fdc000 0%,#fe8900 100%);background: -o-linear-gradient(top, #fdc000 0%,#fe8900 100%);background: -ms-linear-gradient(top, #fdc000 0%,#fe8900 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#fdc000', endColorstr='#fe8900',GradientType=0 );background:linear-gradient(top, #fdc000 0%,#fe8900 100%);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, .6), 0 1px 0 rgba(255,255,255,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, .6), 0 1px 0 rgba(255,255,255,.6) inset;box-shadow:0 1px 0 rgba(255, 255, 255, .6), 0 1px 0 rgba(255,255,255,.6) inset;border:1px
solid #ae5d00;border-radius:5px}.form-screen-button:hover{background:#fcc932;background: -moz-linear-gradient(top, #fcc932 0%, #fc9e32 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fcc932), color-stop(100%,#fc9e32));background: -webkit-linear-gradient(top, #fcc932 0%,#fc9e32 100%);background: -o-linear-gradient(top, #fcc932 0%,#fc9e32 100%);background: -ms-linear-gradient(top, #fcc932 0%,#fc9e32 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcc932', endColorstr='#fc9e32',GradientType=0 );background:linear-gradient(top, #fcc932 0%,#fc9e32 100%);border:1px
solid #ae5d00}.form-screen-button:active{background:#fe8900;background: -moz-linear-gradient(top, #fe8900 0%, #fdc000 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fe8900), color-stop(100%,#fdc000));background: -webkit-linear-gradient(top, #fe8900 0%,#fdc000 100%);background: -o-linear-gradient(top, #fe8900 0%,#fdc000 100%);background: -ms-linear-gradient(top, #fe8900 0%,#fdc000 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#fe8900', endColorstr='#fdc000',GradientType=0 );background:linear-gradient(top, #fe8900 0%,#fdc000 100%);border:1px
solid #C56600;-moz-box-shadow:0 1px 0 rgba(255, 255, 255, .6), 0 -1px 0 rgba(255,255,255,.6) inset;-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, .6), 0 -1px 0 rgba(255,255,255,.6) inset;box-shadow:0 1px 0 rgba(255, 255, 255, .6), 0 -1px 0 rgba(255,255,255,.6) inset}.form-screenshot-plate{background:url("/images/noises/defaultdesktop.png") repeat scroll 0 0 transparent;border:2px
solid #545454;border-radius:3px 3px 3px 3px;box-shadow:0 0 5px rgba(0, 0, 0, 0.7) inset;margin:10px
0;text-align:center}.form-screenshot-img{box-shadow:0 0 5px rgba(0, 0, 0, 0.7);margin:14px
0;display:inline-block}.form-screenshot-img
img{}.form-submit-print::-moz-focus-inner{padding:0px
6px}.form-submit-print{padding:1px
6px}.form-submit-print
img{margin-left: -14px;margin-right:3px;margin-top: -3px}.form-submit-print{margin-bottom: -4px;margin-top: -6px;margin-left: -6px;margin-right:5px}.form-submit-button-img{border:none !important;margin:0
!important;padding:0
!important;background:none !important;cursor:pointer !important}.form-collapse-right{position:absolute;right:0px;height:58px;width:40px}.form-collapse-right-show{background:url(/images/arrow-open.png) no-repeat center}.form-collapse-right-hide{background:url(/images/arrow-closed.png) no-repeat center}.form-collapse-hidden{display:none}.form-grading-item{margin-bottom:3px}.form-header{margin:0px}.form-footer{margin:0px;text-align:center;font-size:9px;color:#999;font-weight:300}.form-subHeader{border-top:1px solid #ccc;font-style:italic}.form-header-group{background:#f5f5f5;border-bottom:1px solid #ccc;padding:12px;clear:both}.form-footer-group{padding:12px;clear:both}.form-label{width:150px;margin-bottom:6px;display:inline-block;white-space:normal}.form-label-top{margin-bottom:6px;display:block;white-space:normal}.form-label-left{float:left;display:inline-block;text-align:left;padding:3px;white-space:normal}.form-label-right{float:left;display:inline-block;text-align:right;margin-bottom:6px;padding:3px;white-space:normal}.form-input-wide{}.form-section,.form-section-closed{list-style:none;list-style-position:outside;margin:0px;padding:0px;position:relative;zoom:1;clear:both}.form-section-closed{overflow:hidden;height:60px}.form-input{display:inline-block}.form-line{clear:both;padding:10px;margin:0px;display:block;width:97%;width:-moz-available;position:relative}.form-line-column{float:left;clear:none;width:auto;white-space:nowrap}.form-line.form-line-column{display:inline-block}.form-line-column-clear{clear:left;width:auto}.form-line-active{background-color:#FFFFE0;color:#333}.form-matrix-table{border-collapse:collapse;font-size:10px;margin-bottom:5px}.form-matrix-column-headers{border:1px
solid #ccc;background:#ddd;color:inherit;text-align:center}.form-matrix-row-headers{border:1px
solid #ccc;background:#ddd}.form-matrix-values{border:1px
solid #ccc;background:#f5f5f5}.form-pagebreak{border-top:1px solid #ccc;background:#f5f5f5;height:60px;clear:left}.form-pagebreak-back-container,.form-pagebreak-next-container{float:left;padding:10px;padding-top:14px}.form-pagebreak-next-container{padding-left:0px}.form-pagebreak-back,.form-pagebreak-next{-webkit-border-radius:5px 5px;-webkit-box-shadow:0px 1px 2px #aaa;-moz-border-radius:5px 5px;-moz-box-shadow:0px 1px 2px #aaa;border-radius:5px 5px;box-shadow:0px 1px 2px #aaa;border:1px
solid #999;background:#ddd;padding:5px;margin:0px;font-size:14px}.form-pagebreak-next{margin:0
0 0 20px}.button-hidden{display:none}.form-required{margin-left:5px;color:red}.form-scale-table{font-size:12px}.form-scale-table
th{border-bottom:1px solid #ccc;color:#999}.form-product-details{font-size:9px;color:#999;font-style:italic}.form-address-table{width:330px}.form-address-line{width:310px}.form-address-city,.form-address-state{width:144px}.form-address-table td, .form-address-table
th{padding-bottom:10px}.form-address-table
select{width:150px}.form-button-error{color:red;display:inline;text-align:center}.form-pagebreak>.form-button-error{padding:14px
10px 10px;display:block}.form-line-error{background:#FAA;color:#333}.form-line-error input:not(#coupon-input), .form-line-error textarea,.form-validation-error{border:1px
solid red;-moz-box-shadow:0 0 2px red;-webkit-box-shadow:0 0 2px red;box-shadow:0 0 2px red}.form-validation-error.form-input{border:none}.form-line-active .form-error-message{display:none}.form-error-message{z-index:900;position:absolute;max-width:130px;right:0px;top:0px;color:#333;padding:3px;font-size:10px;border:4px
solid #d88;-webkit-box-shadow:0px 2px 4px rgba(102, 102, 102, 0.5);-webkit-border-radius:6px 6px;-moz-box-shadow:0px 2px 4px rgba(102, 102, 102, 0.5);-moz-border-radius:6px 6px;box-shadow:0px 2px 4px rgba(102, 102, 102, 0.5);border-radius:6px 6px;background:#FCC}.form-error-arrow{position:absolute;top:-20px;left:10px;height:0px;width:0px;border:10px
solid transparent;border-bottom-color:#666;border-bottom:10px solid rgba(102,102,102,0.3)}.form-error-arrow-inner{position:absolute;top:1px;height:0px;width:0px;border:10px
solid transparent;border-bottom-color:#FCC;border-bottom-width:11px;left:-10px;top:-10px}.form-input .form-error-message, .form-input-wide .form-error-message{bottom:-5px;font-size:11px;position:relative;z-index:900;right:auto;top:auto;color:#333;padding:3px;max-width:100%;padding-bottom:3px;font-size:12px;border:none;-moz-box-shadow:0px 2px 4px rgba(102, 102, 102, 0.5);-webkit-box-shadow:0px 2px 4px rgba(102, 102, 102, 0.5);-moz-border-radius:6px 6px;-webkit-border-radius:6px 6px;box-shadow:0px 2px 4px rgba(102, 102, 102, 0.5);border-radius:6px 6px;background:#FCC}.form-description{z-index:1000;position:absolute;right:7px;max-width:150px;top:6px;border:4px
solid #ccc;-webkit-border-radius:6px 6px;-webkit-box-shadow:0px 2px 4px #666;-moz-border-radius:6px 6px;-moz-box-shadow:0px 2px 4px #666;border-radius:6px 6px;box-shadow:0px 2px 4px #666;background:#f5f5f5;white-space:normal}.form-description-content{padding:10px;font-size:10px;color:#333}.form-description-arrow{border-color:transparent #CCC transparent transparent;border-style:solid;border-width:10px;height:0;width:0;left:-24px;top:7px;position:absolute}.form-description-arrow-small{border-color:transparent #F5F5F5 transparent transparent;border-style:solid;border-width:7px;height:0;width:0;left:-14px;top:10px;position:absolute}.right{right:33px !important;float:none !important}.form-line:hover .form-description-indicator, .form-line-active .form-description-indicator{display:block}.form-description-indicator{display:none;height:100%;position:absolute;right:0;top:0;width:25px;background:url(/images/s-info.png) no-repeat center}.right .form-description-arrow{border-color:transparent transparent transparent #CCC;left:auto;right:-24px}.right .form-description-arrow-small{border-color:transparent transparent transparent #F5F5F5;left:auto;right:-14px}.form-autocomplete-list{font-family:Verdana,Geneva,Arial,Helvetica,sans-serif;font-size:12px;background:#333;background:rgba(26,58,81,0.8);border:1px
solid #eee;border-top:none;padding:5px
0;-moz-border-radius-bottomright:10px 10px;-moz-border-radius-bottomleft:10px 10px;-moz-box-shadow:0px 5px 10px rgba(0,0,0,0.6);-webkit-border-bottom-right-radius:10px 10px;-webkit-border-bottom-left-radius:10px 10px;-webkit-box-shadow:0px 5px 10px rgba(0,0,0,0.6);border-radius-bottom-right:10px 10px;border-radius-bottom-left:10px 10px;box-shadow:0px 5px 10px rgba(0,0,0,0.6)}.form-autocomplete-list-item{margin:0
5px;border:1px
solid transparent;color:#fff;padding:3px;-moz-border-radius:5px 5px;-webkit-border-radius:5px;border-radius:5px 5px;text-shadow:1px 1px 3px #000;cursor:pointer}.form-autocomplete-list-item-selected,.form-autocomplete-list-item:hover{-moz-box-shadow:0 0 4px #333;-webkit-box-shadow:0 0 4px #333;box-shadow:0 0 4px #333;border:1px
solid #1a3a51;background:#4295D1}.form-autocomplete-list-item:hover{border:1px
solid #ccc}.form-sub-label-container{display:inline-block;margin-right:5px;white-space:nowrap}.form-sub-label{color:#999;display:block;font-size:9px}.form-html{padding:3px;white-space:normal}.form-radio-other-input,.form.checkbox-other-input{margin-left:5px}.form-spinner-input-td{white-space:normal}.form-spinner-input-td input[type="number"]::-webkit-inner-spin-button,
.form-spinner-input-td input[type="number"]::-webkit-outer-spin-button{display:none}.edit-hover{display:none}.form-custom-hint{color:#aaa !important;overflow:hidden !important}.filePicker-button{border-style:solid;border-width:1px;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);cursor:pointer;display:inline-block;vertical-align:middle;padding:9px
24px;margin-bottom:0;font-size:13px;line-height:18px;text-align:center;color:#FFF;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background:#0074CC;background: -moz-linear-gradient(top, #08c 0%, #05c 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#0088cc), color-stop(100%,#0055cc));background: -webkit-linear-gradient(top, #08c 0%,#05c 100%);background: -o-linear-gradient(top, #08c 0%,#05c 100%);background: -ms-linear-gradient(top, #08c 0%,#05c 100%);background:linear-gradient(to bottom, #08c 0%,#05c 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#0088cc', endColorstr='#0055cc',GradientType=0 );-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0,0,0,0.05)}.filePicker-button:hover{background:#00a0f0;background: -moz-linear-gradient(top, #00a0f0 0%, #0064f0 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#00a0f0), color-stop(100%,#0064f0));background: -webkit-linear-gradient(top, #00a0f0 0%,#0064f0 100%);background: -o-linear-gradient(top, #00a0f0 0%,#0064f0 100%);background: -ms-linear-gradient(top, #00a0f0 0%,#0064f0 100%);background:linear-gradient(to bottom, #00a0f0 0%,#0064f0 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#00a0f0', endColorstr='#0064f0',GradientType=0 )}.filePicker-button:active{background:#0064f0;background: -moz-linear-gradient(top, #0064f0 0%, #00a0f0 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#0064f0), color-stop(100%,#00a0f0));background: -webkit-linear-gradient(top, #0064f0 0%,#00a0f0 100%);background: -o-linear-gradient(top, #0064f0 0%,#00a0f0 100%);background: -ms-linear-gradient(top, #0064f0 0%,#00a0f0 100%);background:linear-gradient(to bottom, #0064f0 0%,#00a0f0 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#0064f0', endColorstr='#00a0f0',GradientType=0 )}.qq-uploader{position:relative;width:224px}.qq-upload-button{background:#ffa84c;background: -moz-linear-gradient(top, #FBCB5D 0%, #EFA003 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#FBCB5D), color-stop(100%,#EFA003));filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#FBCB5D', endColorstr='#EFA003',GradientType=0 );color:#FFF;display:block;font-size:16px;padding:8px
0;text-align:center;text-shadow:0 -1px #C64F00;border:1px
solid #C64F00;-moz-border-radius:5px 5px;-webkit-border-radius:5px 5px;border-radius:5px 5px}.qq-upload-button-hover{background:#ff7b0d;background: -moz-linear-gradient(top, #ff7b0d 0%, #ffa84c 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ff7b0d), color-stop(100%,#ffa84c));filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff7b0d', endColorstr='#ffa84c',GradientType=0 )}.qq-upload-button-focus{outline:1px
dotted black}.qq-upload-delete{display:none;top:0px;position:absolute;background:#f85032;background: -moz-linear-gradient(top, #f85032 0%, #f16f5c 50%, #f6290c 51%, #f02f17 71%, #e73827 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f85032), color-stop(50%,#f16f5c), color-stop(51%,#f6290c), color-stop(71%,#f02f17), color-stop(100%,#e73827));filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#f85032', endColorstr='#e73827',GradientType=0 );width:20px;height:20px;right:0px;color:#fff;line-height:18px;text-align:center;text-shadow:0 -1px 0px #000;-moz-border-radius:0px 5px 5px 0px;-webkit-border-radius:0px 5px 5px 0px;border-radius:0px 5px 5px 0px;border-left:1px solid #aaa;cursor:pointer}.qq-upload-delete:hover{background:#ffb76b;background: -moz-linear-gradient(top, #ffb76b 0%, #ffa73d 50%, #ff7c00 51%, #ff7f04 100%);background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffb76b), color-stop(50%,#ffa73d), color-stop(51%,#ff7c00), color-stop(100%,#ff7f04));filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffb76b', endColorstr='#ff7f04',GradientType=0 )}.qq-upload-list li:hover{border:1px
solid #aaa}.qq-upload-list li:hover .qq-upload-delete{display:block}.qq-upload-drop-area{position:absolute;top:0;left:0;width:100%;height:100%;min-height:54px;z-index:2;background:#F5F5F5;background:rgba(240, 240, 240, 0.9);text-align:center;color:#B1B1B1;border:2px
dashed #c5c5c5;-moz-border-radius:5px 5px;-webkit-border-radius:5px 5px;border-radius:5px 5px}.qq-upload-drop-area
span{display:block;position:absolute;top:50%;width:100%;margin-top:-10px;font-size:16px}.qq-upload-drop-area-active{background:lightyellow;background:rgba(222,255,210,0.9)}.qq-upload-list{margin:10px
0;padding:0;list-style:none}.qq-upload-list
li{position:relative;font-size:11px;margin:8px
0;color:#5E5B5B;padding:2px
4px;background:#EEE;-moz-border-radius:5px 5px;-webkit-border-radius:5px 5px;border-radius:5px 5px;white-space:normal;border:1px
solid transparent}.qq-upload-file,.qq-upload-spinner,.qq-upload-size,.qq-upload-cancel,.qq-upload-failed-text{font-size:9px;line-height:16px}.qq-file-uploading{display:inline-block;overflow:hidden;white-space:nowrap;width:80px}.qq-upload-failed-text{float:right}.qq-upload-fail{background:#FF927D !important;color:#fff !important}.qq-upload-fail .qq-upload-size{display:none !important}.qq-upload-file{}.qq-upload-spinner{display:inline-block;background:url("/images/loading.gif");width:15px;height:15px;vertical-align:text-bottom;margin-bottom:3px;margin-left:2px}.qq-upload-size,.qq-upload-cancel{float:right;margin-left:4px}.qq-upload-failed-text{display:none}.qq-upload-fail .qq-upload-failed-text{display:inline}.fb-login-wrapper{}.fb-align-auto,.fb-align-center{}.fb-align-left{}.fb-align-right{}.fb-login-label{color:#888;font-size:11px;line-height:23px}.fb-login-button{}.paypalpro_img{width:40px;height:26px;padding-right:7px}.paypalpro_visa{background:url('/images/credit-card-logo.png') no-repeat 0 0}.paypalpro_mc{background:url('/images/credit-card-logo.png') no-repeat -47px 0}.paypalpro_amex{background:url('/images/credit-card-logo.png') no-repeat -94px 0}.paypalpro_dc{background:url('/images/credit-card-logo.png') no-repeat -141px 0}#recaptcha_logo{display:none}#recaptcha_tagline{display:none}#recaptcha_table{border:none !important}.recaptchatable .recaptcha_image_cell,#recaptcha_table{background-color:transparent !important}#recaptcha_table
td{padding-left:0px !important}.form-single-column
.clearfix{display:inline-block}.form-single-column
.clearfix{display:block}@media only screen and (max-device-width: 550px){body{font-size:18px}.form-all{width:auto !important}.form-label-left{float:none;display:block}.form-buttons-wrapper{margin:5px
!important;text-align:center}.form-submit-print{display:none}.form-textarea{width:94% !important}.form-textbox,.form-textarea,.form-dropdown,.form-list{border:1px
solid #555;padding:4px;-webkit-border-radius:5px 5px;-webkit-box-shadow:0 2px 4px rgba(0,0,0, 0.4) inset;-moz-border-radius:5px 5px;-moz-box-shadow:0 2px 4px rgba(0,0,0, 0.4) inset;border-radius:5px 5px;box-shadow:0 2px 4px rgba(0,0,0, 0.4) inset}.form-address-table{width:300px}.form-address-line{width:280px}.form-address-city,.form-address-state{width:130px}.form-address-table td, .form-address-table
th{padding-bottom:10px}.form-address-table
select{width:120px}.form-spinner{border-collapse:inherit !important;border:1px
solid #555 !important;-webkit-border-radius:5px 5px;-webkit-box-shadow:0 2px 4px rgba(0,0,0, 0.4) inset;-moz-border-radius:5px 5px;-moz-box-shadow:0 2px 4px rgba(0,0,0, 0.4) inset;border-radius:5px 5px;box-shadow:0 2px 4px rgba(0,0,0, 0.4) inset}.form-spinner-up,.form-spinner-down{padding:0
8px !important;border:none !important;border-left:1px solid #555 !important}.form-spinner-up{-moz-border-radius-topright:5px 5px;-webkit-border-top-right-radius:5px 5px;border-top-right-radius:5px 5px;border-bottom:1px solid #555 !important}.form-spinner-down{-moz-border-radius-bottomright:5px 5px;-webkit-border-bottom-right-radius:5px 5px;border-bottom-right-radius:5px 5px}.form-spinner-input-td{padding-right:6px !important}.form-spinner-input-td
input{padding:4px
!important;background:none}.form-sub-label-container img[id*="pick"]{width:25px}div.form-header-group{margin:0px
!important}div.form-pagebreak .form-label-left{display:inline-block !important;float:left}.form-submit-button,.form-submit-reset{font-size:18px;line-height:30px}.form-captcha{border:1px
solid #555}.form-captcha
input{width:120px !important}}.clearfix2:before,.clearfix2:after{content:" ";display:table}.clearfix2:after{clear:both}div.calendar{color:#000;font-family:Verdana,Geneva,Arial,Helvetica,sans-serif;-moz-box-shadow:0px 0px 8px rgba(0, 0, 0, 0.5);-webkit-box-shadow:0px 0px 8px rgba(0, 0, 0, 0.5);box-shadow:0px 0px 8px rgba(0,0,0,0.5)}div.calendar.popup{margin-left: -40px;margin-top: -100px;z-index:100000}div.calendar
td.weekend{background:#b5cfe9}div.calendar
.today{background:#f9621a !important}div.calendar .title, div.calendar
.button{color:#f9621a}div.calendar
table{background-color:#eee;border:1px
solid #aaa;border-collapse:collapse}div.calendar
thead{background-color:white}div.calendar td,
div.calendar
th{font-size:11px;padding:3px;text-align:center}div.calendar
td.title{font-weight:bold}div.calendar
th{background:#ddd;border-bottom:1px solid #ccc;border-top:1px solid #ccc;font-weight:bold;color:#555}div.calendar tr.days
td{width:2em;color:#555;text-align:center;cursor:pointer}div.calendar tr.days td:hover,
div.calendar td.button:hover{background-color:#34ABFA;cursor:pointer}div.calendar tr.days td:active
div.calendar td.button:active{background-color:#cde}div.calendar tr.days
td.selected{font-weight:bold;background-color:#fff;color:#000}div.calendar tr.days
td.today{font-weight:bold;color:#D50000}div.calendar tr.days
td.otherDay{color:#bbb}

View file

@ -1,50 +0,0 @@
/**
* CSS rules added to override those in existing stylesheets in the interests of better look'n'feel
*/
/* this lot taken from an embedded style element within the jot form */
.form-label{
/* width:149px !important; */
}
.form-label-left{
/* width:149px !important; */
}
.form-line{
list-style: none;
margin: 0.5 0.5em;
/* padding-top:12px;
padding-bottom:12px; */
}
.form-label-right{
/* width:149px !important; */
}
body, html{
margin:0;
padding:0;
background:false;
}
.form-all{
margin:0px auto;
/* padding-top:20px;
width:390px; */
color:#555 !important;
font-family:'Arial';
/* font-size:12px; */
}
.form-radio-item label, .form-checkbox-item label, .form-grading-label, .form-header {
color:#555;
}
.form-required {
color: red;
}
/* end of group from the embedded style element within the jot form */

View file

@ -6,14 +6,10 @@ body {
/* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */
#main-container{
clear: both;
width:80%;
margin: 0 10%;
padding: 0;
padding-top: 12em;
padding-bottom: 2em;
width:100%;
}
/* footer of the document, within #main-container */
/* footer of the document */
#footer {
clear: both;
font-size: smaller;
@ -33,12 +29,8 @@ body {
#header {
width:100%;
margin: -10px;
padding: 0.25em 10%;
position: fixed;
z-index: 149;
padding: 2em 10% 0.25em 10%;
background-color: black;
background-repeat: no-repeat;
color: white;
}
@ -53,10 +45,11 @@ body {
#nav{
float: left;
margin: 0;
min-height: 56px;
width: 60%;
width: 100%;
position: fixed;
z-index: 149;
background:rgba(40,40,40,0.8);
}
#nav ul li {
@ -69,14 +62,15 @@ body {
color: white;
text-decoration: none;
font-weight: bold;
padding: 0.25em 0.75em;
padding: 0.1em 0.75em;
margin: 0;
}
#nav ul li.active a { background: silver;}
li.nav-item a:hover { background: rgb( 240, 240, 240) }
li.nav-item a:active { background: gray; color: white; }
.error {
background-color: #663399;;
background-color: red;
color: white;
}
@ -107,9 +101,11 @@ h1 {
h1, h2, h3, h4, h5 {
background-color: black;
color: white;
padding-left: -20px;
}
p, pre, ul, ol, dl, h1, h2, h3, h4, h5 {
padding: 0.25em 10%;
}
input {
background-color: white;
@ -124,8 +120,11 @@ input.required:after {
color: red;
}
label {
min-width: 35%;
}
label, input {
width: 45%;
padding: 0.25em 1em;
margin: 0 0.5em;
}

View file

@ -3063,20 +3063,11 @@ further rules can be applied.</p>
(cond
(ifn? rule) (apply-rule cell world rule nil)
(seq? rule) (let [[afn src] rule] (apply-rule cell world afn src))))
;; {:afn afn :src src})))
;; (apply-rule cell world (first rule) (first (rest rule)))))
([cell world rule source]
(try
(let [result (apply rule (list cell world))]
(cond
(and result source) (merge result {:rule source})
true result))
(catch Exception e
(merge cell {:error (format &quot;%s at generation %d when in state %s&quot;
(.getMessage e)
(:generation cell)
(:state cell))
:error-rule source})))))</pre></td></tr><tr><td class="docs"><p>Derive a cell from this cell of this world by applying these rules.</p>
true result))))</pre></td></tr><tr><td class="docs"><p>Derive a cell from this cell of this world by applying these rules.</p>
</td><td class="codes"><pre class="brush: clojure">(defn- apply-rules
[cell world rules]
(cond (empty? rules) cell
@ -3098,12 +3089,13 @@ further rules can be applied.</p>
(:state cell))}))))</pre></td></tr><tr><td class="docs"><p>Return a row derived from this row of this world by applying these rules to each cell.</p>
</td><td class="codes"><pre class="brush: clojure">(defn- transform-world-row
[row world rules]
(map #(transform-cell % world rules) row))</pre></td></tr><tr><td class="docs"><p>Return a world derived from this world by applying these rules to each cell.</p>
(apply vector (map #(transform-cell % world rules) row)))</pre></td></tr><tr><td class="docs"><p>Return a world derived from this world by applying these rules to each cell.</p>
</td><td class="codes"><pre class="brush: clojure">(defn transform-world
[world rules]
(apply vector
(map
#(transform-world-row % world rules)
world))</pre></td></tr><tr><td class="docs"><p>Consider this single argument as a map of <code>:world</code> and <code>:rules</code>; apply the rules
world)))</pre></td></tr><tr><td class="docs"><p>Consider this single argument as a map of <code>:world</code> and <code>:rules</code>; apply the rules
to transform the world, and return a map of the new, transformed <code>:world</code> and
these <code>:rules</code>. As a side effect, print the world.</p>
</td><td class="codes"><pre class="brush: clojure">(defn- transform-world-state
@ -3486,7 +3478,7 @@ that every cell's :x and :y properties reflect its place in the matrix.</p>
* `width` total width of the matrix, in cells;
* `height` total height of the matrix, in cells.&quot;
(cond (= index height) nil
true (cons (make-world-row 0 width index)
true (cons (apply vector (make-world-row 0 width index))
(make-world-rows (+ index 1) width height))))</pre></td></tr><tr><td class="docs"><p>Make a world width cells from east to west, and height cells from north to
south.</p>
@ -3496,7 +3488,7 @@ that every cell's :x and :y properties reflect its place in the matrix.</p>
</ul>
</td><td class="codes"><pre class="brush: clojure">(defn make-world
[width height]
(make-world-rows 0 width height))</pre></td></tr><tr><td class="docs"><p>Truncate the print name of the state of this cell to at most limit characters.</p>
(apply vector (make-world-rows 0 width height)))</pre></td></tr><tr><td class="docs"><p>Truncate the print name of the state of this cell to at most limit characters.</p>
</td><td class="codes"><pre class="brush: clojure">(defn truncate-state
[cell limit]
(let [s (:state cell)]

View file

Before

Width:  |  Height:  |  Size: 779 B

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

View file

@ -12,28 +12,23 @@ represented as a map having at least the following properties:
* **y** The Y offset of this cell within the array (should not be tampered with).
* **state** The current state of this cell, represented as a clojure key; initially :waste.
As currently initialised all cells have two additional properties:
* **altitude** Altitude of this cell. Initially 1. Currently not used.
* **fertility** Soil fertility of this cell. Initially 1. Increases under climax forest; later, will decrease under ploughland, may increase under pasture.
Rules can add any additional properties to cells that you like; the current
'natural-rules' rule-set adds properties for the populations of deer and of
'ecology' rule-set adds properties for the populations of deer and of
wolves.
### Representation of rules
Rules are just ordinary Clojure functions (can be anonymous functions, and in the current
rule-sets they are) which take two arguments, a cell and a world, and return
either nil (indicating the rule did not fire), or a new cell which should have
the same :x and :y properties as the cell passed in. Any other properties can
be different.
Rules are simple production rules, in a [grammar](docs#grammar) defined in the
documentation. Each rule is compiled into a Clojure anonymous function of two
arguments, **world** and **cell**, which if its conditions are met returns a
new cell which must the same **x** and **y** values as the cell which was
passed. Any other properties may be modified.
## What is MicroWorld for
The underlying intention is to crudely model the evolution of human settlement
in a landscape, but also to act as a learning environment to teach ideas about
software and about ecology.
software and about geography and ecology.
## User interface
@ -45,19 +40,5 @@ of the world cell.
The 'state' classes are defined in a CSS file 'states.css', which should be
edited when you add additional states. Image files should be 32x32 pixels and
should be stored in the directory 'img/tiles', but at this stage I haven't
created any.
## Future plans
### Run in the browser
Currently the simulation runs on the server and only the display is in the
browser. It would be much better converted to ClojureScript and run in the browser
- that would save both network traffic and server load, and would allow the
animation to run faster.
### Rule language
It would be good to have a near-English rule parser to make rules easier for
children to add and modify.
should be stored in the directory 'img/tiles', be in PNG format, and have a
name comprising the name of the state followed by '.png'.

View file

@ -1,21 +0,0 @@
### Managing Your Middleware
Two middleware functions are provided by default in the `mw-ui.middleware` namespace.
* `log-request` - logs all requests using the debug level
* `template-error-page` - provides friendly formatting for Selmer errors in dev mode
See the `:middleware` key of the `app` definition located in the `mw-ui.handler` namespace to manage the enabled middleware.
### Here are some links to get started
1. [HTML templating](http://www.luminusweb.net/docs/html_templating.md)
2. [Accessing the database](http://www.luminusweb.net/docs/database.md)
3. [Serving static resources](http://www.luminusweb.net/docs/static_resources.md)
4. [Setting response types](http://www.luminusweb.net/docs/responses.md)
5. [Defining routes](http://www.luminusweb.net/docs/routes.md)
6. [Adding middleware](http://www.luminusweb.net/docs/middleware.md)
7. [Sessions and cookies](http://www.luminusweb.net/docs/sessions_cookies.md)
8. [Security](http://www.luminusweb.net/docs/security.md)
9. [Deploying the application](http://www.luminusweb.net/docs/deployment.md)

View file

@ -0,0 +1,10 @@
## Lesson plans
I haven't actually written any lesson plans, since I'm not a teacher and that
isn't my skill. If you use MicroWorld in class, and find it useful, and would
like to contribute a lesson plan, please mail it to [me](mailto:simon@journeyman.cc).
Ideally your lesson plan should be written in 'markdown' style, the very simple
style which is used in this document and other documentation within the program,
but frankly it doesn't matter - I'll accept them in any format, including hand
written notes or even (gasp) Microsoft Word.

View file

@ -0,0 +1,3 @@
## No content file was found?
No content file was found. Are you sure the right one was specified?

View file

@ -19,7 +19,6 @@
<meta content="{{pause}}" http-equiv="{{maybe-refresh}}" />
</head>
<body>
<div id="header" style="background-image: url( '{{servlet-context}}/img/earth-space-strip.jpg');">
<div id="nav">
<ul class="nav">
<li class="{{home-selected}}"><a href="{{servlet-context}}/">Home</a></li>
@ -29,8 +28,10 @@
<li class="{{about-selected}}"><a href="{{servlet-context}}/about">About</a></li>
<li class="{{docs-selected}}"><a href="{{servlet-context}}/docs">Documentation</a></li>
</ul>
<h1>{{title}}</h1>
</div>
<div id="header">
<h1>{{title}}</h1>
</div>
<div id="main-container" class="container">

View file

@ -7,6 +7,7 @@
<li><a href="#grammar">Rule language</a></li>
<li><a href="#states">Implemented states</a></li>
<li><a href="#api">API documentation</a></li>
<li><a href="#teachers">For teachers</a></li>
</menu>
<hr/>
<a name="parser"/>
@ -17,6 +18,7 @@
<li><a href="#grammar">Rule language</a></li>
<li><a href="#states">Implemented states</a></li>
<li><a href="#api">API documentation</a></li>
<li><a href="#teachers">For teachers</a></li>
</menu>
<hr/>
<h2><a name="states">Implemented states</h2>
@ -42,6 +44,7 @@
<li><a href="#grammar">Rule language</a></li>
<li><a href="#states">Implemented states</a></li>
<li><a href="#api">API documentation</a></li>
<li><a href="#teachers">For teachers</a></li>
</menu>
<hr/>
<h2><a name="api">API documentation</a></h2>
@ -58,5 +61,110 @@
</li>
{% endfor %}
</ul>
<hr/>
<menu>
<li><a href="#top">Top</a></li>
<li><a href="#grammar">Rule language</a></li>
<li><a href="#states">Implemented states</a></li>
<li><a href="#api">API documentation</a></li>
<li><a href="#teachers">For teachers</a></li>
</menu>
<hr/>
<h2><a name="teachers">For teachers</a></h2>
<p>MicroWorld was written in the hope that it would be of use for teachers,
including teachers in primary schools. The reason for attempting to write
a very simple rule language was that young people would be able to create
their own rules and rule sets.</p>
<h3>Classroom setup</h3>
<p>MicroWorld will run on a Raspberry Pi, and I plan to produce a
downloadable SD card image which auto-runs it. One ideal classroom setup
would be to have one Raspberry Pi running MicroWorld to every group of
two or three children.</p>
<p>MicroWorld will also run on any ordinary PC, including Windows,
Macintosh and Linux machines. I plan to produce a packaged installer
for each operating system.</p>
<h4>Servers and clients</h4>
<p>MicroWorld is a web-app, which means it runs in a web server and the
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
machine running MicroWorld from that single server.</p>
<p>However, performance isn't very good, and unless you have an unusually
powerful server you may find that when a full class of pupils are running
MicroWorld from a single server performance may be frustratingly poor.
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
satisfactory.</p>
<h3>Subject areas</h3>
<p>One of my main objectives in writing MicroWorld was to create a system
which would be engaging for children and would enable them to see
computing in the context of other subject areas.</p>
<h4>Geography</h4>
<p>Maps of Great Britain and Ireland, and of the Isle of Man, are included
in the distribution; however, only the 'small' version of the map of
Great Britain and Ireland is really useable, the others are too big and
will be two slow. However, you can cut a map of your local area from the
larger maps if that is helpful to your class.</p>
<p>The following rulesets are of potential use in geography teaching:</p>
<dl>
<dt>basic</dt>
<dd>A very simple ruleset which simply establishes vegetation in the
landscape. Not particularly useful in itself, but a good ruleset for
children to use as a basis for their own projects.</dd>
<dt>iceage<dt>
<dd>illustrates ice thawing gradually. Because of inadequacies in the
rule language, currently the ice retreats from north to south, which is
of course wrong for the northern hemisphere; but the principle of
retreating ice, the way in which ice retreats up mountains, and the way
in which ecosystems establish themselves.</dd>
<dt>ecology</dt>
<dd>Attempts to model the effects of browsers and predators - represented
by deer and wolves, respectively - on the landscape.</dd>
<dt>settlement</dt>
<dd>illustrates human settlement appearing first on coastal promontaries
(e.g. kitchen-midden people), gradually spreads inland (in this model as
nomadic pastoralists), and forms permanent settlements where conditions
are favourable. This helps explore why the towns in your locality are
where they are. The model is obviously simplified, but produces a
potentially useful account of settlement in at least north-western Europe
from paleolithic up to at least late bronze age. <b>Note</b> that unless
your map has at least some coastal promontaries this ruleset will need
to be modified.</dd>
<dt>
</dl>
<p>All of these rulesets are deliberately simple. This is so that
children have something to start with, but so that they can actually make
real, demonstrable improvements quite simply.</p>
<h4>History</h4>
<p>The <em>settlement</em> ruleset is probably the best starting point for
history exploration. As described above, it essentially covers only
pre-history; the development of the feudal system, for example, or of
industrialisation, are not modelled. They could be, as (more advanced)
class projects. Writing rules will enable discussion of why castles, or
mills, are positioned where they are, and what the social consequences of
these developments are.</p>
<h4>IT/Informatics</h4>
<p>Obviously, any of the rulesets but particularly the <em>gameoflife</em>
ruleset are good introduction points to informatics lessons. The rule
language is sufficiently simple that introducing children to writing
their own rules can begin almost as soon as basic literacy is
established.</p>
<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
itself in your classes.</p>
<h3>Lesson plans</h3>
<ul>
{% for lesson in lessons %}
<li>
<a href="{{servlet-context}}/md?content=lesson-plans/{{lesson}}.md">
{{lesson}}
</a>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

View file

@ -41,7 +41,7 @@
(let [world (or (session/get :world)
(engine/transform-world
(heightmap/apply-heightmap
"resources/public/img/20x20/hill.png"
"resources/public/img/heightmaps/small_hill.png"
;; "resources/public/img/heightmaps/great_britain_and_ireland_small.png"
)
rules/init-rules))

View file

@ -1,5 +1,6 @@
(ns mw-ui.routes.home
(:use compojure.core
(:use clojure.walk
compojure.core
[mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params])
(:require [hiccup.core :refer [html]]
@ -13,13 +14,25 @@
:content (util/md->html "/md/mw-ui.md")}))
(defn world-page []
(layout/render "trusted-content.html" {:title "Watch your world grow"
(layout/render "trusted-content.html"
{:title "Watch your world grow"
:world-selected "active"
:content (html (world/render-world-table))
:pause (or (session/get :pause) 5)
:maybe-refresh "refresh"}))
(defn about-page []
(layout/render "trusted-content.html" {:title "About MicroWorld" :content (util/md->html "/md/about.md")}))
(layout/render "trusted-content.html"
{:title "About MicroWorld"
:about-selected "active"
:content (util/md->html "/md/about.md")}))
(defn md-page [request]
(let [params (keywordize-keys (:params request))
content (or (:content params) "missing.md")]
(layout/render "trusted-content.html"
{:title "Welcome to MicroWorld"
:content (util/md->html (str "/md/" content))})))
(defn list-states []
(sort
@ -31,6 +44,7 @@
(layout/render "docs.html" {:title "Documentation"
:parser (util/md->html "/md/mw-parser.md" )
:states (util/list-resources "resources/public/img/tiles" #"([0-9a-z-_]+).png")
:lessons (util/list-resources "resources/public/md/lesson-plans" #"([0-9a-z-_]+).md")
:components ["mw-engine" "mw-parser" "mw-ui"]}))
(defroutes home-routes
@ -39,6 +53,7 @@
(GET "/docs" [] (docs-page))
(GET "/world" [] (world-page))
(GET "/params" [] (params/params-page))
(GET "/md" request (md-page request))
(POST "/params" request (params/params-page request))
(GET "/rules" request (rules/rules-page request))
(POST "/rules" request (rules/rules-page request)))

View file

@ -10,7 +10,7 @@
[noir.session :as session]))
(defn- send-params []
{{:title "Choose your world"
{:title "Choose your world"
:heightmaps (util/list-resources "resources/public/img/heightmaps" #"([0-9a-z-_]+).png")
:pause (or (session/get :pause) 5)
:rulesets (util/list-resources "resources/rulesets" #"([0-9a-z-_]+).txt")