commit 72d93262169192d311eafcd02455623ccae7d7fc Author: Simon Brooke Date: Tue Jul 18 22:31:57 2023 +0100 Initial commit. A start has been made, but nothing works yet. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7939f15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +/.calva/ +/.clj-kondo/ +/.lsp/ +/target +/classes +/checkouts +profiles.clj +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +/.prepl-port +.hgignore +.hg/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..72b197d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Change Log +All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). + +## [Unreleased] +### Changed +- Add a new arity to `make-widget-async` to provide a different widget shape. + +## [0.1.1] - 2023-07-16 +### Changed +- Documentation on how to make the widgets. + +### Removed +- `make-widget-sync` - we're all async, all the time. + +### Fixed +- Fixed widget maker to keep working when daylight savings switches over. + +## 0.1.0 - 2023-07-16 +### Added +- Files from the new template. +- Widget maker public API - `make-widget-sync`. + +[Unreleased]: https://sourcehost.site/your-name/mw-desktop/compare/0.1.1...HEAD +[0.1.1]: https://sourcehost.site/your-name/mw-desktop/compare/0.1.0...0.1.1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4e955b9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,258 @@ +# GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to guarantee +your freedom to share and change free software--to make sure the software is free +for all its users. This General Public License applies to most of the Free +Software Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by the GNU +Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must make +sure that they, too, receive or can get the source code. And you must show them +these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish +to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +## TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice + placed by the copyright holder saying it may be distributed under the terms of + this General Public License. The "Program", below, refers to any such program + or work, and a "work based on the Program" means either the Program or any + derivative work under copyright law: that is to say, a work containing the + Program or a portion of it, either verbatim or with modifications and/or + translated into another language. (Hereinafter, translation is included without + limitation in the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not covered by + this License; they are outside its scope. The act of running the Program is not + restricted, and the output from the Program is covered only if its contents + constitute a work based on the Program (independent of having been made by + running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as + you receive it, in any medium, provided that you conspicuously and appropriately + publish on each copy an appropriate copyright notice and disclaimer of warranty; + keep intact all the notices that refer to this License and to the absence of any + warranty; and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and you may at + your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus + forming a work based on the Program, and copy and distribute such modifications + or work under the terms of Section 1 above, provided that you also meet all of + these conditions: + + a) You must cause the modified files to carry prominent notices stating that + you changed the files and the date of any change. + b) You must cause any work that you distribute or publish, that in whole or in + part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of this + License. + c) If the modified program normally reads commands interactively when run, you + must cause it, when started running for such interactive use in the most + ordinary way, to print or display an announcement including an appropriate + copyright notice and a notice that there is no warranty (or else, saying + that you provide a warranty) and that users may redistribute the program + under these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but does not + normally print such an announcement, your work based on the Program is not + required to print an announcement.) + + These requirements apply to the modified work as a whole. If identifiable + sections of that work are not derived from the Program, and can be reasonably + considered independent and separate works in themselves, then this License, + and its terms, do not apply to those sections when you distribute them as + separate works. But when you distribute the same sections as part of a whole + which is a work based on the Program, the distribution of the whole must be on + the terms of this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your + rights to work written entirely by you; rather, the intent is to exercise the + right to control the distribution of derivative or collective works based on + the Program. + + In addition, mere aggregation of another work not based on the Program with the + Program (or with a work based on the Program) on a volume of a storage or + distribution medium does not bring the other work under the scope of this + License. + + 3. You may copy and distribute the Program (or a work based on it, under + Section 2) in object code or executable form under the terms of Sections 1 + and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, + which must be distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange; or, + b) Accompany it with a written offer, valid for at least three years, to give + any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + c) Accompany it with the information you received as to the offer to distribute + corresponding source code. (This alternative is allowed only for + noncommercial distribution and only if you received the program in object + code or executable form with such an offer, in accord with Subsection b + above.) + + The source code for a work means the preferred form of the work for making + modifications to it. For an executable work, complete source code means all the + source code for all modules it contains, plus any associated interface + definition files, plus the scripts used to control compilation and installation + of the executable. However, as a special exception, the source code distributed + need not include anything that is normally distributed (in either source or + binary form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component itself + accompanies the executable. + + If distribution of executable or object code is made by offering access to + copy from a designated place, then offering equivalent access to copy the + source code from the same place counts as distribution of the source code, + even though third parties are not compelled to copy the source along with the + object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as + expressly provided under this License. Any attempt otherwise to copy, modify, + sublicense or distribute the Program is void, and will automatically + terminate your rights under this License. However, parties who have + received copies, or rights, from you under this License will not have their + licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. + However, nothing else grants you permission to modify or distribute the + Program or its derivative works. These actions are prohibited by law if + you do not accept this License. Therefore, by modifying or distributing + the Program (or any work based on the Program), you indicate your + acceptance of this License to do so, and all its terms and conditions + for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), + the recipient automatically receives a license from the original licensor + to copy, distribute or modify the Program subject to these terms and + conditions. You may not impose any further restrictions on the recipients' + exercise of the rights granted herein. You are not responsible for enforcing + compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement + or for any other reason (not limited to patent issues), conditions are + imposed on you (whether by court order, agreement or otherwise) that + contradict the conditions of this License, they do not excuse you from the + conditions of this License. If you cannot distribute so as to satisfy + simultaneously your obligations under this License and any other pertinent + obligations, then as a consequence you may not distribute the Program at + all. For example, if a patent license would not permit royalty-free + redistribution of the Program by all those who receive copies directly or + indirectly through you, then the only way you could satisfy both it and + this License would be to refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under any + particular circumstance, the balance of the section is intended to apply + and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents + or other property right claims or to contest validity of any such claims; + this section has the sole purpose of protecting the integrity of the free + software distribution system, which is implemented by public license + practices. Many people have made generous contributions to the wide range + of software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to decide if he or + she is willing to distribute software through any other system and a + licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a + consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain + countries either by patents or by copyrighted interfaces, the original + copyright holder who places the Program under this License may add an + explicit geographical distribution limitation excluding those countries, + so that distribution is permitted only in or among countries not thus + excluded. In such case, this License incorporates the limitation as if + written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the + General Public License from time to time. Such new versions will be similar + in spirit to the present version, but may differ in detail to address new + problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and + "any later version", you have the option of following the terms and + conditions either of that version or of any later version published + by the Free Software Foundation. If the Program does not specify a version + number of this License, you may choose any version ever published by the + Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs + whose distribution conditions are different, write to the author to ask for + permission. For software which is copyrighted by the Free Software + Foundation, write to the Free Software Foundation; we sometimes make + exceptions for this. Our decision will be guided by the two goals of + preserving the free status of all derivatives of our free software and of + promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR + THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO + THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM + PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR + CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL + ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..60c5a5c --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# mw-desktop + +A desktop interface to MicroWorld, using Swing + +## Installation + +Download from http://example.com/FIXME. + +## Usage + +FIXME: explanation + + java -jar mw-desktop-0.1.0-standalone.jar [args] + +## Options + +FIXME: listing of options this app accepts. + +## Examples + +... + +### Bugs + +... + +### Any Other Sections +### That You Think +### Might be Useful + +## License + +Copyright © 2023 Simon Brooke + +This program and the accompanying materials are made available under the +terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or (at your +option) any later version, with the GNU Classpath Exception which is available +at https://www.gnu.org/software/classpath/license.html. diff --git a/doc/intro.md b/doc/intro.md new file mode 100644 index 0000000..cafc032 --- /dev/null +++ b/doc/intro.md @@ -0,0 +1,3 @@ +# Introduction to mw-desktop + +TODO: write [great documentation](http://jacobian.org/writing/what-to-write/) diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..f0c807f --- /dev/null +++ b/project.clj @@ -0,0 +1,20 @@ +(defproject mw-desktop "0.1.0-SNAPSHOT" + :description "FIXME: write description" + :url "http://example.com/FIXME" + :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" + :url "https://www.eclipse.org/legal/epl-2.0/"} + :dependencies [[cljfx "1.7.23"] + [de.codecentric.centerdevice/javafxsvg "1.3.0"] ;; used by markdown-editor-example + [markdown-clj "1.11.4"] + [mw-engine "0.2.0-SNAPSHOT"] + [mw-parser "0.2.0-SNAPSHOT"] + [net.sourceforge.htmlcleaner/htmlcleaner "2.29"] + [org.clojure/clojure "1.10.3"] + [org.clojure/core.cache "1.0.225"] + [org.clojure/tools.cli "1.0.214"] + [org.commonmark/commonmark "0.21.0"] + [seesaw "1.5.0"]] + :main ^:skip-aot mw-desktop.core + :target-path "target/%s" + :profiles {:uberjar {:aot :all + :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}}) diff --git a/resources/doc/grammar.md b/resources/doc/grammar.md new file mode 100644 index 0000000..78286d3 --- /dev/null +++ b/resources/doc/grammar.md @@ -0,0 +1,155 @@ +## What this is about + +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 +in steps, and at each step, each cell is modified by applying the rules. + +The demonstration world is a mountain, with snow at the top and the sea at the +bottom. as you watched, you probably saw the bright green of grass on the lower +slopes of the mountain turn to the darker green of forest. You may have seen +some forest fires break out. + +That's all controlled by rules. You make the rules. To start Noah's flood, +[go to the rules page](rules) now, and add this rule at the very top: + + if altitude is less than 200 then state should be water + +then, [go and watch the world](world) again. What happens? You should see water +spread across everywhere except the very top of the mountain. But after the +flood, the waters should drain away again. Go back to [rules](rules) and add +this rule at the very top: + + if altitude is more than 9 and state is water then state should be grassland + +Now the world alternates between *new* and *grassland*. That's no good! Go back to +[rules](rules) and delete the rule that you first added - the one that says + + if altitude is less than 200 then state should be water + +And see! The world starts growing again. + +## What you can do next + +### Change some rules + +Change some of the other rules and see what happens. Very likely, one of the +first things that will happen is that you will get a message like this: + + I did not understand 'if state is grassland then 1 chance in 10 state will be heath' + +That means that you changed a rule in a way that the engine could no longer +understand it. To find out what the engine will understand, have a look at the +[documentation](docs#grammar). + +### Invent some rules of your own + +What happens when people come into the world? Where would they make their first +camp? Would they want to be near the water, so they could fish? Would they want +be near fertile grassland, to graze their sheep and cattle? + +__Write a rule which adds some camps to the world__ + +What happens to the land around a camp? Do the people burn down forest to make +new grassland? Do they convert the grassland into meadow, or into crop? + +Does growing crops reduce the soil fertility? What makes people decide that their +camp is a good enough place to build a proper house? + +__Write some rules which describe this__ + +How many squares of meadow or crop does it take to feed each house full of people? +What happens when there are too many houses and not enough fields? Can houses +catch fire? What happens to a house which is next to a fire? + +How many houses do you need for a market place? Where would people build a +harbour? + +### Change the rules completely + +I've provided rules which use the MicroWorld cellular automaton to make a simple +model of the changes to land in Europe after the ice age. But you don't have to +use it like that, at all. + +[Conway's Game of Life](http://en.wikipedia.org/wiki/Conway's_Game_of_Life) is one +of the famous uses of a cellular automaton. The rules for the Game of Life are +very simple. To set up your game of life you'll need some initialisation rules, +one for every cell you want to start live (we'll use *black* for live, and +*white* for dead): + + if x is equal to 4 and y is equal to 4 and state is new then state should be black + +Add as many of these as you need for your starting pattern. Then add a rule, after +all those: + + if state is new then state should be white + +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 +[Leiningen](https://github.com/technomancy/leiningen) 2.0 or above installed on +your own computer, and you'll need to download the source, and unpack it. + +You will find that there are three packages: + ++ __mw-engine__ deals with creating worlds, and transforming them; ++ __mw-parser__ deals with turning the rule language into something the engine can work on; ++ __mw-ui__ is the web site which provides you with a user interface. + +For each of these packages, you need to run, in the root directory of the package, +the following command: + + lein install + +Once you've done that, you'll have everything built. To start a web server for +the application, run the following command in the *mw-ui* directory: + + lein ring server + +Now you have it working, you can start changing things. + +#### Add states + +Adding new states is easy: +just add new tiles in *mw-ui/resources/public/img/tiles*. The tiles should be +png (Portable Network Graphics) files, and should be 32 pixels square. The name +of the tile should be the name of your new state. It's good to also edit the file +*mw-ui/resources/public/css/states.css* to add a class for your new state. + +#### Change the code + +Once you've done all that, you're ready to be really ambitious. Change the code. +Implement some new feature I haven't thought of, or fix bugs I've accidentally +left in. + +You'll need an editor. I recommend either [NightCode](https://nightcode.info/), +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 + +Copyright © 2014-2023 [Simon Brooke](mailto:simon@journeyman.cc) + +Distributed under the terms of the +[GNU General Public License v2](http://www.gnu.org/licenses/gpl-2.0.html) diff --git a/resources/doc/grammar.rtf b/resources/doc/grammar.rtf new file mode 100644 index 0000000..5c68b6b --- /dev/null +++ b/resources/doc/grammar.rtf @@ -0,0 +1,99 @@ +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 What this is about\par} +{\pard \ql \f0 \sa180 \li0 \fi0 MicroWorld is a rule driven cellular automaton. What does that mean? Well, it\u8217's a two dimensional world made up of squares called {\b cells}. The world develops in steps, and at each step, each cell is modified by applying the rules.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 The demonstration world is a mountain, with snow at the top and the sea at the bottom. as you watched, you probably saw the bright green of grass on the lower slopes of the mountain turn to the darker green of forest. You may have seen some forest fires break out.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 That\u8217's all controlled by rules. You make the rules. To start Noah\u8217's flood, {\field{\*\fldinst{HYPERLINK "rules"}}{\fldrslt{\ul +go to the rules page +}}} + now, and add this rule at the very top:\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 if altitude is less than 200 then state should be water\par} +{\pard \ql \f0 \sa180 \li0 \fi0 then, {\field{\*\fldinst{HYPERLINK "world"}}{\fldrslt{\ul +go and watch the world +}}} + again. What happens? You should see water spread across everywhere except the very top of the mountain. But after the flood, the waters should drain away again. Go back to {\field{\*\fldinst{HYPERLINK "rules"}}{\fldrslt{\ul +rules +}}} + and add this rule at the very top:\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 if altitude is more than 9 and state is water then state should be grassland\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Now the world alternates between {\i new} and {\i grassland}. That\u8217's no good! Go back to {\field{\*\fldinst{HYPERLINK "rules"}}{\fldrslt{\ul +rules +}}} + and delete the rule that you first added - the one that says\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 if altitude is less than 200 then state should be water\par} +{\pard \ql \f0 \sa180 \li0 \fi0 And see! The world starts growing again.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 What you can do next\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Change some rules\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Change some of the other rules and see what happens. Very likely, one of the first things that will happen is that you will get a message like this:\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 I did not understand 'if state is grassland then 1 chance in 10 state will be heath'\par} +{\pard \ql \f0 \sa180 \li0 \fi0 That means that you changed a rule in a way that the engine could no longer understand it. To find out what the engine will understand, have a look at the {\field{\*\fldinst{HYPERLINK "docs#grammar"}}{\fldrslt{\ul +documentation +}}} +.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Invent some rules of your own\par} +{\pard \ql \f0 \sa180 \li0 \fi0 What happens when people come into the world? Where would they make their first camp? Would they want to be near the water, so they could fish? Would they want be near fertile grassland, to graze their sheep and cattle?\par} +{\pard \ql \f0 \sa180 \li0 \fi0 {\b Write a rule which adds some camps to the world}\par} +{\pard \ql \f0 \sa180 \li0 \fi0 What happens to the land around a camp? Do the people burn down forest to make new grassland? Do they convert the grassland into meadow, or into crop?\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Does growing crops reduce the soil fertility? What makes people decide that their camp is a good enough place to build a proper house?\par} +{\pard \ql \f0 \sa180 \li0 \fi0 {\b Write some rules which describe this}\par} +{\pard \ql \f0 \sa180 \li0 \fi0 How many squares of meadow or crop does it take to feed each house full of people? What happens when there are too many houses and not enough fields? Can houses catch fire? What happens to a house which is next to a fire?\par} +{\pard \ql \f0 \sa180 \li0 \fi0 How many houses do you need for a market place? Where would people build a harbour?\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Change the rules completely\par} +{\pard \ql \f0 \sa180 \li0 \fi0 I\u8217've provided rules which use the MicroWorld cellular automaton to make a simple model of the changes to land in Europe after the ice age. But you don\u8217't have to use it like that, at all.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 {\field{\*\fldinst{HYPERLINK "http://en.wikipedia.org/wiki/Conway's_Game_of_Life"}}{\fldrslt{\ul +Conway\u8217's Game of Life +}}} + is one of the famous uses of a cellular automaton. The rules for the Game of Life are very simple. To set up your game of life you\u8217'll need some initialisation rules, one for every cell you want to start live (we\u8217'll use {\i black} for live, and {\i white} for dead):\par} +{\pard \ql \f0 \sa180 \li0 \fi0 if x is equal to 4 and y is equal to 4 and state is new then state should be black\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Add as many of these as you need for your starting pattern. Then add a rule, after all those:\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 if state is new then state should be white\par} +{\pard \ql \f0 \sa180 \li0 \fi0 I\u8217'll leave you to work out what the rules of life are for yourself, from the Wiki page I linked to.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 {\b CHEAT} {\i You\u8217'll find other rule sets you can explore if you go to the} {\i {\field{\*\fldinst{HYPERLINK "params"}}{\fldrslt{\ul +Parameters +}}} + page}.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs28 Change the engine\par} +{\pard \ql \f0 \sa180 \li0 \fi0 If you want to modify the engine itself, you will need {\field{\*\fldinst{HYPERLINK "https://github.com/technomancy/leiningen"}}{\fldrslt{\ul +Leiningen +}}} + 2.0 or above installed on your own computer, and you\u8217'll need to download the source, and unpack it.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 You will find that there are three packages:\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\b mw-engine} deals with creating worlds, and transforming them;\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\b mw-parser} deals with turning the rule language into something the engine can work on;\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 \bullet \tx360\tab {\b mw-ui} is the web site which provides you with a user interface.\sa180\par} +{\pard \ql \f0 \sa180 \li0 \fi0 For each of these packages, you need to run, in the root directory of the package, the following command:\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 lein install\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Once you\u8217've done that, you\u8217'll have everything built. To start a web server for the application, run the following command in the {\i mw-ui} directory:\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \f1 lein ring server\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Now you have it working, you can start changing things.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 Add states\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Adding new states is easy: just add new tiles in {\i mw-ui/resources/public/img/tiles}. The tiles should be png (Portable Network Graphics) files, and should be 32 pixels square. The name of the tile should be the name of your new state. It\u8217's good to also edit the file {\i mw-ui/resources/public/css/states.css} to add a class for your new state.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 Change the code\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Once you\u8217've done all that, you\u8217're ready to be really ambitious. Change the code. Implement some new feature I haven\u8217't thought of, or fix bugs I\u8217've accidentally left in.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 You\u8217'll need an editor. I recommend either {\field{\*\fldinst{HYPERLINK "https://nightcode.info/"}}{\fldrslt{\ul +NightCode +}}} +, which is quite small and will run on a Raspberry Pi, or {\field{\*\fldinst{HYPERLINK "http://www.lighttable.com/"}}{\fldrslt{\ul +LightTable +}}} +, which is extremely helpful but needs a more powerful computer.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs24 Worthwhile projects\par} +{\pard \ql \f0 \sa180 \li0 \fi0 If you would like to work on the engine, there\u8217's things that would be worth improving:\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 1.\tx360\tab Better arithmetic in actions\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 2.\tx360\tab Better arithmetic in conditions - it would be useful to be able to say {\i \u8216'if generation is more than 64 - y then state should be snow\u8217'}. This would make the ice retreat in the right direction in the iceage rule set.\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 3.\tx360\tab Better error messages when rules don\u8217't parse, explaining where the problem occured {\i (very hard)}.\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 4.\tx360\tab Make this all work in ClojureScript in the browser, so there\u8217's less load on the server and one server can support more users {\i (quite hard)}.\par} +{\pard \ql \f0 \sa0 \li360 \fi-360 5.\tx360\tab Optimisation: MicroWorld runs quite slowly, you can\u8217't really do big maps and one server won\u8217't support many users. There must be many ways performance can be improved.\sa180\par} +{\pard \ql \f0 \sa180 \li0 \fi0 If you make changes which you think improve MicroWorld, please {\field{\*\fldinst{HYPERLINK "mailto:simon@journeyman.cc"}}{\fldrslt{\ul +mail them to me +}}} +.\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Have fun!\par} +{\pard \ql \f0 \sa180 \li0 \fi0 \b \fs32 License\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Copyright \u169? 2014-2023 {\field{\*\fldinst{HYPERLINK "mailto:simon@journeyman.cc"}}{\fldrslt{\ul +Simon Brooke +}}} +\par} +{\pard \ql \f0 \sa180 \li0 \fi0 Distributed under the terms of the {\field{\*\fldinst{HYPERLINK "http://www.gnu.org/licenses/gpl-2.0.html"}}{\fldrslt{\ul +GNU General Public License v2 +}}} +\par} + diff --git a/resources/doc/markdown.css b/resources/doc/markdown.css new file mode 100644 index 0000000..39629d1 --- /dev/null +++ b/resources/doc/markdown.css @@ -0,0 +1,148 @@ +* { + -fx-line-spacing: 4; + -fx-font-family: Ubuntu; + -fx-font-size: 14; + -fx-text-fill: #ddd; + -fx-fill: #ddd; +} + +.root { + -fx-background-color: #444; +} + +.scroll-pane { + -fx-background-color: transparent; + bottom-padding: 2em; + -fx-bottom-padding: 2em; +} +.scroll-pane > .viewport { + -fx-background-color: transparent; + padding: 3em; +} +.scroll-pane > .scroll-bar { + -fx-background-color: transparent; +} +.scroll-pane > .scroll-bar > .increment-button, +.scroll-pane > .scroll-bar > .increment-button > .increment-arrow, +.scroll-pane > .scroll-bar > .decrement-button, +.scroll-pane > .scroll-bar > .decrement-button > .decrement-arrow { + -fx-padding: 0; +} +.scroll-pane > .corner { + -fx-background-color: transparent; +} +.scroll-pane > .scroll-bar > .thumb { + -fx-background-color: #888; + -fx-background-radius: 10; + -fx-background-insets: 0; + -fx-padding: 0; +} +.scroll-pane > .scroll-bar > .track { + -fx-background-color: #0002; + -fx-background-radius: 10; +} +.scroll-pane > .scroll-bar:vertical { + -fx-pref-width: 10; +} +.scroll-pane > .scroll-bar:horizontal { + -fx-pref-height: 10; +} + +.document { + -fx-padding: 30; +} + +.heading.level-1 { + -fx-padding: 16 0 0 0; +} +.heading.level-1 * { + -fx-font-weight: bold; + -fx-font-size: 30; +} + +.heading.level-2 { + -fx-padding: 14 0 0 0; +} +.heading.level-2 * { + -fx-font-weight: bold; + -fx-font-size: 26; +} + +.heading.level-3 { + -fx-padding: 12 0 0 0; +} +.heading.level-3 * { + -fx-font-weight: bold; + -fx-font-size: 22; +} + +.heading.level-4 { + -fx-padding: 10 0 0 0; +} +.heading.level-4 * { + -fx-font-weight: bold; + -fx-font-size: 20; +} + +.heading.level-5 { + -fx-padding: 8 0 0 0; +} +.heading.level-5 * { + -fx-font-weight: bold; + -fx-font-size: 18; +} + +.paragraph { + -fx-padding: 10 0 0 0; +} + +.code { + -fx-background-color: #0002; + -fx-background-radius: 4; + -fx-background-insets: -1; +} +.code * { + -fx-font-family: "Ubuntu Mono"; +} + +.code-block { + -fx-padding: 10; + -fx-margin: 10; + -fx-background-color: #0002; + -fx-background-radius: 4; +} +.code-block * { + -fx-font-family: "Ubuntu Mono"; +} + +.hyperlink { + -fx-border-color: transparent; + -fx-padding: 0; +} +.hyperlink * { + -fx-border-color: transparent; + -fx-padding: 0; + -fx-fill: #9ce; +} +.hyperlink:visited { + -fx-underline: false; +} +.hyperlink:hover { + -fx-underline: true; +} + +.md-list { + -fx-padding: 0 0 0 20; +} + +.strong-emphasis { + -fx-font-weight: bold; +} + +.emphasis { + -fx-font-style: italic; +} + +.input { + -fx-font-family: "Ubuntu Mono"; +} diff --git a/resources/doc/mw-parser.md b/resources/doc/mw-parser.md new file mode 100644 index 0000000..76f662d --- /dev/null +++ b/resources/doc/mw-parser.md @@ -0,0 +1,216 @@ +# mw-parser + +A rule parser for MicroWorld + +## Part of the overall MicroWorld system + +While this code works and is interesting on its own, you also need at least +[mw-engine](https://github.com/simon-brooke/mw-engine) and +[mw-ui](https://github.com/simon-brooke/mw-ui). There will be other +modules in due course. + +You can see MicroWorld in action [here](http://www.journeyman.cc/microworld/) - +but please don't be mean to my poor little server. If you want to run big maps +or complex rule-sets, please run it on your own machines. + +## Usage + +Main entry point is (parse-rule _string_), where string takes a form detailed +in __[grammar](#grammar)__, below. If the rule is interpretted correctly the result will +be the source code of a Clojure anonymous function; if the rule cannot be interpretted, +an error 'I did not understand...' will be shown. + +The function (compile-rule _string_) is like parse-rule, except that it returns +a compiled Clojure anonymous function. + +### Generated function and evaluation environment + +The generated function is a function of two arguments + ++ __cell__ a cell in a world as defined in mw-engine.world, q.v.; ++ __world__ the world of which that cell forms part. + +It returns a new cell, based on the cell passed. + +Actions of the rule will (can only) modify properties of the cell; there are two +properties which are special and SHOULD NOT be modified, namely the properties +__x__ and __y__. + +### Execution + +Each time the world is transformed, exactly the same set of rules is applied to every +cell. The rules are applied to the cell in turn, in the order in which they are +written in the rule text, until the conditions of one of them match the cell. +The actions of that rule are then used to transform the cell, and the rest of +the rules are not applied. + +So, for example, if your first rule is + + if x is more than -1 then state should be new + +then no matter what your other rules are, your world will never change, because +all cells have x more than -1. + +If you are having problems because one of your rules isn't working, look to +see whether there is another rule above it which is 'blocking' it. + +### Grammar + +#### Comments + ++ Any line which starts with the hash character (#) is ignored; ++ Any line which starts with a semi-colon (;) is ignored. + +#### Rules + +A rule comprises: + ++ if _conditions_ then _actions_ + +Each rule must be on a single line. There should be nothing else on that line. + +#### Conditions + +In rules, _conditions_ is one of: + ++ _condition_ ++ _condition_ and _conditions_ ++ _condition_ or _conditions_ + +Note that 'and' takes precedence over or, so + + conditionA and conditionB or conditionC and conditionD + +is interpreted as + + (conditionA and (conditionB or (conditionC and conditionD))) + +A _condition_ is one of: + ++ _property_ is _value_ ++ _property_ is not _value_ ++ _property_ is in _values_ ++ _property_ is not in _values_ ++ _property_ is more than _numeric-value_ ++ _property_ is less than _numeric-value_ ++ _number_ neighbours have _property_ equal to _value_ ++ _number_ neighbours have _property_ more than _numeric-value_ ++ _number_ neighbours have _property_ less than _numeric-value_ ++ more than _number_ neighbours have _property_ equal to _value_ ++ fewer than _number_ neighbours have _property_ equal to _value_ ++ some neighbours have _property_ equal to _value_ ++ more than _number_ neighbours have _property_ more than _numeric-value_ ++ fewer than _number_ neighbours have _property_ more than _numeric-value_ ++ some neighbours have _property_ more than _numeric-value_ ++ more than _number_ neighbours have _property_ less than _numeric-value_ ++ fewer than _number_ neighbours have _property_ less than _numeric-value_ ++ some neighbours have _property_ less than _numeric-value_ + +#### About neighbours + +Note that everywhere above I've used 'neighbours', you can use 'neighbours +within _distance_', where _distance_ is a (small) positive integer. + +A cell has eight immediate neighbours - cells which actually touch it (except +for cells on the edge of the map, which have fewer). If the cell we're +interested in is the cell marked 'X' in the table below, its immediate neighbours +are the ones marked '1'. But outside the ones marked '1', it has more distant +neighbours - those marked '2' and '3' in the table, and still more outside those. + + + + + + + + + +
3333333
3222223
3211123
321X123
3211123
3222223
3333333
+ +If a rule just says 'neighbours', and not 'neighbours within', it means +'neighbours within 1'; so + + if some neighbours are scrub then state should be scrub + +has exactly the same meaning as + + if some neighbours within 1 are scrub then state should be scrub + +#### Actions + +In these rules, _actions_ is one of: + ++ _action_ ++ _action_ and _actions_ + +and _action_ is: + ++ _property_ should be _value_ ++ _number_ chance in _number_ _property_ should be _value_ + +#### Properties + +In the above, _property_ is the name of any property of a cell. Any alpha-numeric +string of characters can form the name of a property. Actions should __NOT__ +try to change the reserved properties __x__ and __y__. + +#### Values in Conditions + +Values in conditions and actions are considered slightly differently. In a +condition, a value is one of: + ++ _symbolic-value_ ++ _numeric-value_ + +The '...more than...' and '...less than...' conditions imply a _numeric-value_. +Thus "if altitude is more than fertility..." is interpreted as meaning "if the value +of the property of the current cell called 'altitude' is greater than the value +of the property of the current cell called 'fertility'", whereas the apparently +similar condition 'if altitude is fertility...' is interpreted as meaning +"if the value of the property of the current cell called 'altitude' is the symbol +'fertility'". + +Thus _symbolic-value_ is any sequence of alphanumeric characters, whereas +_numeric-value_ is one of: + ++ _number_ ++ _property_ + +and _number_ is any sequence of the decimal digits 0...9, the minus character +'-' and the period character '.', provided that the minus character can only be +in the first position, and the period character can only appear once. + +#### Values in Actions + +A _value_ in an action is one of + ++ _symbolic-value_ ++ _arithmetic-value_ ++ _number_ + +where _arithmetic-value_ is: + ++ _property_ _operator_ _numeric-value_ + +and _operator_ is one of the simple arithmetic operators '+', '-', '*' and '/'. + +### Shorthand + +Note that '...neighbours are...' is equivalent to '...neighbours have state equal to...', +and 'some neighbours...' is equivalent to 'more than 0 neighbours...' + +### Roadmap + +The existing parser, *mw-parser.core*, works but is not well written. A much +better parser which does not yet completely work, *mw-parser.insta*, is also +included for the adventurous. + +I intend to replace *mw-parser.core* with *mw-parser.insta* as soon as +*mw-parser.insta* correctly parses all the test rules. + +## License + +Copyright © 2014 [Simon Brooke](mailto:simon@journeyman.cc) + +Distributed under the terms of the +[GNU General Public License v2](http://www.gnu.org/licenses/gpl-2.0.html) diff --git a/resources/doc/mw-parser.rtf b/resources/doc/mw-parser.rtf new file mode 100644 index 0000000..3933b3f --- /dev/null +++ b/resources/doc/mw-parser.rtf @@ -0,0 +1,749 @@ +{\rtf1\ansi\deff4\adeflang1025 +{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq2\fcharset0 Cambria;}{\f5\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f6\froman\fprq2\fcharset0 Calibri;}{\f7\froman\fprq2\fcharset0 Consolas;}{\f8\fnil\fprq2\fcharset0 DejaVu Sans;}{\f9\fnil\fprq2\fcharset0 ;}{\f10\fnil\fprq2\fcharset0 Droid Sans Devanagari;}{\f11\fswiss\fprq0\fcharset128 Droid Sans Devanagari;}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red52\green90\blue138;\red79\green129\blue189;\red54\green95\blue145;\red186\green33\blue33;\red144\green32\blue0;\red64\green160\blue112;\red0\green112\blue32;\red187\green102\blue136;\red136\green0\blue0;\red64\green112\blue160;\red96\green160\blue176;\red25\green23\blue124;\red6\green40\blue126;\red102\green102\blue102;\red125\green144\blue41;\red188\green122\blue0;} +{\stylesheet{\s0\snext0\rtlch\af9\afs24\alang1025 \ltrch\lang1033\langfe1033\hich\af4\loch\ql\widctlpar\sb0\sa200\ltrpar\hyphpar0\cf0\f4\fs24\lang1033\kerning0\dbch\af12\langfe1033 Normal;} +{\s1\sbasedon0\snext162\rtlch\af9\afs32\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb480\sa0\keepn\ltrpar\cf18\f6\fs32\b\dbch\af9 Heading 1;} +{\s2\sbasedon0\snext162\rtlch\af9\afs28\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs28\b\dbch\af9 Heading 2;} +{\s3\sbasedon0\snext162\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\b\dbch\af9 Heading 3;} +{\s4\sbasedon0\snext162\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9 Heading 4;} +{\s5\sbasedon0\snext162\rtlch\af9\afs24\ai \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\dbch\af9 Heading 5;} +{\s6\sbasedon0\snext162\rtlch\af9\afs24 \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\dbch\af9 Heading 6;} +{\s7\sbasedon0\snext162\rtlch\af9\afs24 \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\dbch\af9 Heading 7;} +{\s8\sbasedon0\snext162\rtlch\af9\afs24 \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\dbch\af9 Heading 8;} +{\s9\sbasedon0\snext162\rtlch\af9\afs24 \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\dbch\af9 Heading 9;} +{\*\cs15\snext15 Default Paragraph Font;} +{\*\cs16\sbasedon15\snext16 Body Text Char;} +{\*\cs17\sbasedon16\snext17\hich\af7\loch\f7\fs22 Verbatim Char;} +{\*\cs18\sbasedon16\snext18 Section Number;} +{\*\cs19\sbasedon16\snext19\loch\super Footnote Characters;} +{\*\cs20\snext20\loch\super Footnote Anchor;} +{\*\cs21\sbasedon16\snext21\loch\cf18 Hyperlink;} +{\*\cs22\sbasedon17\snext22\hich\af7\loch\cf23\f7\fs22\b KeywordTok;} +{\*\cs23\sbasedon17\snext23\hich\af7\loch\cf21\f7\fs22 DataTypeTok;} +{\*\cs24\sbasedon17\snext24\hich\af7\loch\cf22\f7\fs22 DecValTok;} +{\*\cs25\sbasedon17\snext25\hich\af7\loch\cf22\f7\fs22 BaseNTok;} +{\*\cs26\sbasedon17\snext26\hich\af7\loch\cf22\f7\fs22 FloatTok;} +{\*\cs27\sbasedon17\snext27\hich\af7\loch\cf25\f7\fs22 ConstantTok;} +{\*\cs28\sbasedon17\snext28\hich\af7\loch\cf26\f7\fs22 CharTok;} +{\*\cs29\sbasedon17\snext29\hich\af7\loch\cf26\f7\fs22 SpecialCharTok;} +{\*\cs30\sbasedon17\snext30\hich\af7\loch\cf26\f7\fs22 StringTok;} +{\*\cs31\sbasedon17\snext31\hich\af7\loch\cf26\f7\fs22 VerbatimStringTok;} +{\*\cs32\sbasedon17\snext32\hich\af7\loch\cf24\f7\fs22 SpecialStringTok;} +{\*\cs33\sbasedon17\snext33\hich\af7\loch\cf11\f7\fs22\b ImportTok;} +{\*\cs34\sbasedon17\snext34\hich\af7\loch\cf27\f7\fs22\i CommentTok;} +{\*\cs35\sbasedon17\snext35\hich\af7\loch\cf20\f7\fs22\i DocumentationTok;} +{\*\cs36\sbasedon17\snext36\hich\af7\loch\cf27\f7\fs22\i\b AnnotationTok;} +{\*\cs37\sbasedon17\snext37\hich\af7\loch\cf27\f7\fs22\i\b CommentVarTok;} +{\*\cs38\sbasedon17\snext38\hich\af7\loch\cf23\f7\fs22 OtherTok;} +{\*\cs39\sbasedon17\snext39\hich\af7\loch\cf29\f7\fs22 FunctionTok;} +{\*\cs40\sbasedon17\snext40\hich\af7\loch\cf28\f7\fs22 VariableTok;} +{\*\cs41\sbasedon17\snext41\hich\af7\loch\cf23\f7\fs22\b ControlFlowTok;} +{\*\cs42\sbasedon17\snext42\hich\af7\loch\cf30\f7\fs22 OperatorTok;} +{\*\cs43\sbasedon17\snext43\hich\af7\loch\cf11\f7\fs22 BuiltInTok;} +{\*\cs44\sbasedon17\snext44\hich\af7\loch\f7\fs22 ExtensionTok;} +{\*\cs45\sbasedon17\snext45\hich\af7\loch\cf32\f7\fs22 PreprocessorTok;} +{\*\cs46\sbasedon17\snext46\hich\af7\loch\cf31\f7\fs22 AttributeTok;} +{\*\cs47\sbasedon17\snext47\hich\af7\loch\f7\fs22 RegionMarkerTok;} +{\*\cs48\sbasedon17\snext48\hich\af7\loch\cf27\f7\fs22\i\b InformationTok;} +{\*\cs49\sbasedon17\snext49\hich\af7\loch\cf27\f7\fs22\i\b WarningTok;} +{\*\cs50\sbasedon17\snext50\hich\af7\loch\cf6\f7\fs22\b AlertTok;} +{\*\cs51\sbasedon17\snext51\hich\af7\loch\cf6\f7\fs22\b ErrorTok;} +{\*\cs52\sbasedon17\snext52\hich\af7\loch\f7\fs22 NormalTok;} +{\*\cs53\snext53 ListLabel 1;} +{\*\cs54\snext54 ListLabel 2;} +{\*\cs55\snext55 ListLabel 3;} +{\*\cs56\snext56 ListLabel 4;} +{\*\cs57\snext57 ListLabel 5;} +{\*\cs58\snext58 ListLabel 6;} +{\*\cs59\snext59 ListLabel 7;} +{\*\cs60\snext60 ListLabel 8;} +{\*\cs61\snext61 ListLabel 9;} +{\*\cs62\snext62 ListLabel 10;} +{\*\cs63\snext63 ListLabel 11;} +{\*\cs64\snext64 ListLabel 12;} +{\*\cs65\snext65 ListLabel 13;} +{\*\cs66\snext66 ListLabel 14;} +{\*\cs67\snext67 ListLabel 15;} +{\*\cs68\snext68 ListLabel 16;} +{\*\cs69\snext69 ListLabel 17;} +{\*\cs70\snext70 ListLabel 18;} +{\*\cs71\snext71 ListLabel 19;} +{\*\cs72\snext72 ListLabel 20;} +{\*\cs73\snext73 ListLabel 21;} +{\*\cs74\snext74 ListLabel 22;} +{\*\cs75\snext75 ListLabel 23;} +{\*\cs76\snext76 ListLabel 24;} +{\*\cs77\snext77 ListLabel 25;} +{\*\cs78\snext78 ListLabel 26;} +{\*\cs79\snext79 ListLabel 27;} +{\*\cs80\snext80 ListLabel 28;} +{\*\cs81\snext81 ListLabel 29;} +{\*\cs82\snext82 ListLabel 30;} +{\*\cs83\snext83 ListLabel 31;} +{\*\cs84\snext84 ListLabel 32;} +{\*\cs85\snext85 ListLabel 33;} +{\*\cs86\snext86 ListLabel 34;} +{\*\cs87\snext87 ListLabel 35;} +{\*\cs88\snext88 ListLabel 36;} +{\*\cs89\snext89 ListLabel 37;} +{\*\cs90\snext90 ListLabel 38;} +{\*\cs91\snext91 ListLabel 39;} +{\*\cs92\snext92 ListLabel 40;} +{\*\cs93\snext93 ListLabel 41;} +{\*\cs94\snext94 ListLabel 42;} +{\*\cs95\snext95 ListLabel 43;} +{\*\cs96\snext96 ListLabel 44;} +{\*\cs97\snext97 ListLabel 45;} +{\*\cs98\snext98 ListLabel 46;} +{\*\cs99\snext99 ListLabel 47;} +{\*\cs100\snext100 ListLabel 48;} +{\*\cs101\snext101 ListLabel 49;} +{\*\cs102\snext102 ListLabel 50;} +{\*\cs103\snext103 ListLabel 51;} +{\*\cs104\snext104 ListLabel 52;} +{\*\cs105\snext105 ListLabel 53;} +{\*\cs106\snext106 ListLabel 54;} +{\*\cs107\snext107 ListLabel 55;} +{\*\cs108\snext108 ListLabel 56;} +{\*\cs109\snext109 ListLabel 57;} +{\*\cs110\snext110 ListLabel 58;} +{\*\cs111\snext111 ListLabel 59;} +{\*\cs112\snext112 ListLabel 60;} +{\*\cs113\snext113 ListLabel 61;} +{\*\cs114\snext114 ListLabel 62;} +{\*\cs115\snext115 ListLabel 63;} +{\*\cs116\snext116 ListLabel 64;} +{\*\cs117\snext117 ListLabel 65;} +{\*\cs118\snext118 ListLabel 66;} +{\*\cs119\snext119 ListLabel 67;} +{\*\cs120\snext120 ListLabel 68;} +{\*\cs121\snext121 ListLabel 69;} +{\*\cs122\snext122 ListLabel 70;} +{\*\cs123\snext123 ListLabel 71;} +{\*\cs124\snext124 ListLabel 72;} +{\*\cs125\snext125 ListLabel 73;} +{\*\cs126\snext126 ListLabel 74;} +{\*\cs127\snext127 ListLabel 75;} +{\*\cs128\snext128 ListLabel 76;} +{\*\cs129\snext129 ListLabel 77;} +{\*\cs130\snext130 ListLabel 78;} +{\*\cs131\snext131 ListLabel 79;} +{\*\cs132\snext132 ListLabel 80;} +{\*\cs133\snext133 ListLabel 81;} +{\*\cs134\snext134 ListLabel 82;} +{\*\cs135\snext135 ListLabel 83;} +{\*\cs136\snext136 ListLabel 84;} +{\*\cs137\snext137 ListLabel 85;} +{\*\cs138\snext138 ListLabel 86;} +{\*\cs139\snext139 ListLabel 87;} +{\*\cs140\snext140 ListLabel 88;} +{\*\cs141\snext141 ListLabel 89;} +{\*\cs142\snext142 ListLabel 90;} +{\*\cs143\snext143 ListLabel 91;} +{\*\cs144\snext144 ListLabel 92;} +{\*\cs145\snext145 ListLabel 93;} +{\*\cs146\snext146 ListLabel 94;} +{\*\cs147\snext147 ListLabel 95;} +{\*\cs148\snext148 ListLabel 96;} +{\*\cs149\snext149 ListLabel 97;} +{\*\cs150\snext150 ListLabel 98;} +{\*\cs151\snext151 ListLabel 99;} +{\*\cs152\snext152 ListLabel 100;} +{\*\cs153\snext153 ListLabel 101;} +{\*\cs154\snext154 ListLabel 102;} +{\*\cs155\snext155 ListLabel 103;} +{\*\cs156\snext156 ListLabel 104;} +{\*\cs157\snext157 ListLabel 105;} +{\*\cs158\snext158 ListLabel 106;} +{\*\cs159\snext159 ListLabel 107;} +{\*\cs160\snext160 ListLabel 108;} +{\s161\sbasedon0\snext162\rtlch\af10\afs28 \ltrch\hich\af5\loch\ql\widctlpar\sb240\sa120\keepn\ltrpar\f5\fs28\dbch\af8 Heading;} +{\s162\sbasedon0\snext162\loch\ql\widctlpar\sb180\sa180\ltrpar Text Body;} +{\s163\sbasedon162\snext163\rtlch\af11 \ltrch\loch\ql\widctlpar\sb180\sa180\ltrpar List;} +{\s164\sbasedon0\snext164\loch\ql\widctlpar\sb0\sa120\ltrpar\i Caption;} +{\s165\sbasedon0\snext165\rtlch\af11\alang255 \ltrch\lang255\langfe255\loch\ql\widctlpar\sb0\sa200\noline\ltrpar\lang255\dbch\langfe255 Index;} +{\s166\sbasedon162\snext162\loch\ql\widctlpar\sb180\sa180\ltrpar First Paragraph;} +{\s167\sbasedon162\snext167\loch\ql\widctlpar\sb36\sa36\ltrpar Compact;} +{\s168\sbasedon0\snext162\rtlch\af9\afs36\ab \ltrch\hich\af6\loch\qc\keep\widctlpar\sb480\sa240\keepn\ltrpar\cf17\f6\fs36\b\dbch\af9 Title;} +{\s169\sbasedon168\snext162\rtlch\af9\afs30\ab \ltrch\hich\af6\loch\qc\keep\widctlpar\sb240\sa240\keepn\ltrpar\cf17\f6\fs30\b\dbch\af9 Subtitle;} +{\s170\snext162\rtlch\af9\afs24\alang1025 \ltrch\lang1033\langfe1033\hich\af4\loch\qc\keep\widctlpar\sb0\sa200\keepn\ltrpar\hyphpar0\cf0\f4\fs24\lang1033\kerning0\dbch\af12\langfe1033 Author;} +{\s171\snext162\rtlch\af9\afs24\alang1025 \ltrch\lang1033\langfe1033\hich\af4\loch\qc\keep\widctlpar\sb0\sa200\keepn\ltrpar\hyphpar0\cf0\f4\fs24\lang1033\kerning0\dbch\af12\langfe1033 Date;} +{\s172\sbasedon0\snext162\rtlch\afs20 \ltrch\loch\ql\keep\widctlpar\sb300\sa300\keepn\ltrpar\fs20 Abstract;} +{\s173\sbasedon0\snext173\loch\ql\widctlpar\sb0\sa200\ltrpar Bibliography;} +{\s174\sbasedon162\snext162\loch\ql\widctlpar\li480\ri480\lin480\rin480\fi0\sb100\sa100\ltrpar Block Text;} +{\s175\sbasedon0\snext175\loch\ql\widctlpar\sb0\sa200\ltrpar Footnote;} +{\s176\sbasedon0\snext177\loch\ql\keep\widctlpar\sb0\sa0\keepn\ltrpar\b Definition Term;} +{\s177\sbasedon0\snext177\loch\ql\widctlpar\sb0\sa200\ltrpar Definition;} +{\s178\sbasedon164\snext178\loch\ql\widctlpar\sb0\sa120\keepn\ltrpar\i Table Caption;} +{\s179\sbasedon164\snext179\loch\ql\widctlpar\sb0\sa120\ltrpar\i Image Caption;} +{\s180\sbasedon0\snext180\loch\ql\widctlpar\sb0\sa200\ltrpar Figure;} +{\s181\sbasedon180\snext181\loch\ql\widctlpar\sb0\sa200\keepn\ltrpar Captioned Figure;} +{\s182\sbasedon161\snext182\rtlch\af10\afs28 \ltrch\hich\af5\loch\ql\widctlpar\sb240\sa120\keepn\ltrpar\f5\fs28\dbch\af8 Index Heading;} +{\s183\sbasedon1\snext162\rtlch\af9\afs32\ab0 \ltrch\hich\af6\loch\sl259\slmult1\ql\keep\widctlpar\sb240\sa0\keepn\ltrpar\cf19\f6\fs32\b0\dbch\af9 Contents Heading;} +{\s184\sbasedon0\snext184\loch\ql\widctlpar\sb0\sa200\ltrpar Source Code;} +}{\*\listtable{\list\listtemplateid1 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid1} +{\list\listtemplateid2 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid2} +{\list\listtemplateid3 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid3} +{\list\listtemplateid4 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid4} +{\list\listtemplateid5 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid5} +{\list\listtemplateid6 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid6} +{\list\listtemplateid7 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid7} +{\list\listtemplateid8 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid8} +{\list\listtemplateid9 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid9} +{\list\listtemplateid10 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid10} +{\list\listtemplateid11 +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li720} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li1440} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li2160} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li2880} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li3600} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li4320} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li5040} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8211 ?;}{\levelnumbers;}\f13\fi-480\li5760} +{\listlevel\levelnfc23\leveljc0\levelstartat0\levelfollow0{\leveltext \'01\u8226 ?;}{\levelnumbers;}\f13\fi-480\li6480}\listid11} +{\list\listtemplateid12 +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0} +{\listlevel\levelnfc255\leveljc0\levelstartat1\levelfollow2{\leveltext \'00;}{\levelnumbers;}\fi0\li0}\listid12} +}{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}{\listoverride\listid6\listoverridecount0\ls6}{\listoverride\listid7\listoverridecount0\ls7}{\listoverride\listid8\listoverridecount0\ls8}{\listoverride\listid9\listoverridecount0\ls9}{\listoverride\listid10\listoverridecount0\ls10}{\listoverride\listid11\listoverridecount0\ls11}{\listoverride\listid12\listoverridecount0\ls12}}{\*\generator LibreOffice/7.3.7.2$Linux_X86_64 LibreOffice_project/e114eadc50a9ff8d8c8a0567d6da8f454beeb84f}{\info{\creatim\yr2023\mo7\dy17\hr20\min42}{\revtim\yr2023\mo7\dy17\hr20\min42}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops{\propname AppVersion}\proptype30{\staticval 12.0000}}\deftab720\deftab720\deftab720 +\hyphauto1\viewscale100 +{\*\pgdsctbl +{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default Page Style;}} +\formshade\paperh15840\paperw12240\margl1440\margr1440\margt1440\margb1440\sectd\sbknone\pgndec\sftnnar\saftnnrlc\sectunlocked1\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc\htmautsp +{\*\ftnsep\chftnsep}\pgndec\pard\plain \s1\rtlch\af9\afs32\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb480\sa0\keepn\ltrpar\cf18\f6\fs32\b\dbch\af9\keep\sb480\sa0\keepn{\loch +{\*\bkmkstart mw-parser}mw-parser} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +A rule parser for MicroWorld} +\par \pard\plain \s2\rtlch\af9\afs28\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs28\b\dbch\af9{\loch +{\*\bkmkstart part-of-the-overall-microworld-system}Part of the overall MicroWorld system} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +While this code works and is interesting on its own, you also need at least }{{\field{\*\fldinst HYPERLINK "https://github.com/simon-brooke/mw-engine" }{\fldrslt {\loch\loch\cf18\loch +mw-engine}{}}}\loch + and }{{\field{\*\fldinst HYPERLINK "https://github.com/simon-brooke/mw-ui" }{\fldrslt {\loch\loch\cf18\loch +mw-ui}{}}}\loch +. There will be other modules in due course.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +You can see MicroWorld in action }{{\field{\*\fldinst HYPERLINK "http://www.journeyman.cc/microworld/" }{\fldrslt {\loch\loch\cf18\loch +here}{}}}\loch + - but please don\u8217\'92t be mean to my poor little server. If you want to run big maps or complex rule-sets, please run it on your own machines.{\*\bkmkend part-of-the-overall-microworld-system}} +\par \pard\plain \s2\rtlch\af9\afs28\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs28\b\dbch\af9{\loch +{\*\bkmkstart usage}Usage} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Main entry point is (parse-rule }{\rtlch\ai \ltrch\loch\i\loch +string}{\loch +), where string takes a form detailed in }{{\field{\*\fldinst HYPERLINK "#grammar" }{\fldrslt {\rtlch\ab \ltrch\loch\loch\cf18\b\loch +grammar}{}}}\loch +, below. If the rule is interpretted correctly the result will be the source code of a Clojure anonymous function; if the rule cannot be interpretted, an error \u8216\'91I did not understand\u8230\'85\u8217\'92 will be shown.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +The function (compile-rule }{\rtlch\ai \ltrch\loch\i\loch +string}{\loch +) is like parse-rule, except that it returns a compiled Clojure anonymous function.} +\par \pard\plain \s3\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\b\dbch\af9{\loch +{\*\bkmkstart X5241f4f5246239745859f6b5bf3a3d94d961d2d}Generated function and evaluation environment} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +The generated function is a function of two arguments} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls1 \li720\ri0\lin720\rin0\fi-480{\rtlch\ab \ltrch\loch\b\loch +cell}{\loch + a cell in a world as defined in mw-engine.world, q.v.;} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls1 \li720\ri0\lin720\rin0\fi-480{\rtlch\ab \ltrch\loch\b\loch +world}{\loch + the world of which that cell forms part.} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +It returns a new cell, based on the cell passed.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Actions of the rule will (can only) modify properties of the cell; there are two properties which are special and SHOULD NOT be modified, namely the properties }{\rtlch\ab \ltrch\loch\b\loch +x}{\loch + and }{\rtlch\ab \ltrch\loch\b\loch +y}{\loch +.{\*\bkmkend X5241f4f5246239745859f6b5bf3a3d94d961d2d}} +\par \pard\plain \s3\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\b\dbch\af9{\loch +{\*\bkmkstart execution}Execution} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Each time the world is transformed, exactly the same set of rules is applied to every cell. The rules are applied to the cell in turn, in the order in which they are written in the rule text, until the conditions of one of them match the cell. The actions of that rule are then used to transform the cell, and the rest of the rules are not applied.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +So, for example, if your first rule is} +\par \pard\plain \s184\loch\ql\widctlpar\sb0\sa200\ltrpar{\loch\cs17\hich\af7\loch\f7\fs22\loch +if x is more than -1 then state should be new} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +then no matter what your other rules are, your world will never change, because all cells have x more than -1.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +{\*\bkmkstart execution}If you are having problems because one of your rules isn\u8217\'92t working, look to see whether there is another rule above it which is \u8216\'91blocking\u8217\'92 it.{\*\bkmkend execution}} +\par \pard\plain \s3\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\b\dbch\af9{\loch +{\*\bkmkstart grammar}Grammar} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart comments}Comments} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls2 \li720\ri0\lin720\rin0\fi-480{\loch +Any line which starts with the hash character (#) is ignored;} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls2 \li720\ri0\lin720\rin0\fi-480{\loch +{\*\bkmkstart comments}Any line which starts with a semi-colon (;) is ignored.{\*\bkmkend comments}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart rules}Rules} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +A rule comprises:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls3 \li720\ri0\lin720\rin0\fi-480{\loch +if }{\rtlch\ai \ltrch\loch\i\loch +conditions}{\loch + then }{\rtlch\ai \ltrch\loch\i\loch +actions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +{\*\bkmkstart rules}Each rule must be on a single line. There should be nothing else on that line.{\*\bkmkend rules}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart conditions}Conditions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +In rules, }{\rtlch\ai \ltrch\loch\i\loch +conditions}{\loch + is one of:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls4 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +condition} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls4 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +condition}{\loch + and }{\rtlch\ai \ltrch\loch\i\loch +conditions} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls4 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +condition}{\loch + or }{\rtlch\ai \ltrch\loch\i\loch +conditions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Note that \u8216\'91and\u8217\'92 takes precedence over or, so} +\par \pard\plain \s184\loch\ql\widctlpar\sb0\sa200\ltrpar{\loch\cs17\hich\af7\loch\f7\fs22\loch +conditionA and conditionB or conditionC and conditionD} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +is interpreted as} +\par \pard\plain \s184\loch\ql\widctlpar\sb0\sa200\ltrpar{\loch\cs17\hich\af7\loch\f7\fs22\loch +(conditionA and (conditionB or (conditionC and conditionD)))} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +A }{\rtlch\ai \ltrch\loch\i\loch +condition}{\loch + is one of:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is not }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is in }{\rtlch\ai \ltrch\loch\i\loch +values} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is not in }{\rtlch\ai \ltrch\loch\i\loch +values} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is more than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is less than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + equal to }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + more than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + less than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +more than }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + equal to }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +fewer than }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + equal to }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +some neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + equal to }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +more than }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + more than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +fewer than }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + more than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +some neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + more than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +more than }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + less than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +fewer than }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + less than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls5 \li720\ri0\lin720\rin0\fi-480{\loch +some neighbours have }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + less than }{\rtlch\ai \ltrch\loch\i\loch +numeric-value{\*\bkmkend conditions}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart about-neighbours}About neighbours} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Note that everywhere above I\u8217\'92ve used \u8216\'91neighbours\u8217\'92, you can use \u8216\'91neighbours within }{\rtlch\ai \ltrch\loch\i\loch +distance}{\loch +\u8217\'92, where }{\rtlch\ai \ltrch\loch\i\loch +distance}{\loch + is a (small) positive integer.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +A cell has eight immediate neighbours - cells which actually touch it (except for cells on the edge of the map, which have fewer). If the cell we\u8217\'92re interested in is the cell marked \u8216\'91X\u8217\'92 in the table below, its immediate neighbours are the ones marked \u8216\'911\u8217\'92. But outside the ones marked \u8216\'911\u8217\'92, it has more distant neighbours - those marked \u8216\'912\u8217\'92 and \u8216\'913\u8217\'92 in the table, and still more outside those.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +X} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +1} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +2} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +3} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +If a rule just says \u8216\'91neighbours\u8217\'92, and not \u8216\'91neighbours within\u8217\'92, it means \u8216\'91neighbours within 1\u8217\'92; so} +\par \pard\plain \s184\loch\ql\widctlpar\sb0\sa200\ltrpar{\loch\cs17\hich\af7\loch\f7\fs22\loch +if some neighbours are scrub then state should be scrub} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +has exactly the same meaning as} +\par \pard\plain \s184\loch\ql\widctlpar\sb0\sa200\ltrpar{\loch\cs17\hich\af7\loch\f7\fs22\loch +{\*\bkmkstart about-neighbours}if some neighbours within 1 are scrub then state should be scrub{\*\bkmkend about-neighbours}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart actions}Actions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +In these rules, }{\rtlch\ai \ltrch\loch\i\loch +actions}{\loch + is one of:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls6 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +action} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls6 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +action}{\loch + and }{\rtlch\ai \ltrch\loch\i\loch +actions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +and }{\rtlch\ai \ltrch\loch\i\loch +action}{\loch + is:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls7 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + should be }{\rtlch\ai \ltrch\loch\i\loch +value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls7 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + chance in }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + should be }{\rtlch\ai \ltrch\loch\i\loch +value{\*\bkmkend actions}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart properties}Properties} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +In the above, }{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + is the name of any property of a cell. Any alpha-numeric string of characters can form the name of a property. Actions should }{\rtlch\ab \ltrch\loch\b\loch +NOT}{\loch + try to change the reserved properties }{\rtlch\ab \ltrch\loch\b\loch +x}{\loch + and }{\rtlch\ab \ltrch\loch\b\loch +y}{\loch +.{\*\bkmkend properties}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart values-in-conditions}Values in Conditions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Values in conditions and actions are considered slightly differently. In a condition, a value is one of:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls8 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +symbolic-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls8 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +The \u8216\'91\u8230\'85more than\u8230\'85\u8217\'92 and \u8216\'91\u8230\'85less than\u8230\'85\u8217\'92 conditions imply a }{\rtlch\ai \ltrch\loch\i\loch +numeric-value}{\loch +. Thus \u8220\'93if altitude is more than fertility\u8230\'85\u8221\'94 is interpreted as meaning \u8220\'93if the value of the property of the current cell called \u8216\'91altitude\u8217\'92 is greater than the value of the property of the current cell called \u8216\'91fertility\u8217\'92\u8221\'94, whereas the apparently similar condition \u8216\'91if altitude is fertility\u8230\'85\u8217\'92 is interpreted as meaning \u8220\'93if the value of the property of the current cell called \u8216\'91altitude\u8217\'92 is the symbol \u8216\'91fertility\u8217\'92\u8221\'94.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Thus }{\rtlch\ai \ltrch\loch\i\loch +symbolic-value}{\loch + is any sequence of alphanumeric characters, whereas }{\rtlch\ai \ltrch\loch\i\loch +numeric-value}{\loch + is one of:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls9 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +number} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls9 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +and }{\rtlch\ai \ltrch\loch\i\loch +number}{\loch + is any sequence of the decimal digits 0\u8230\'859, the minus character \u8216\'91-\u8217\'92 and the period character \u8216\'91.\u8217\'92, provided that the minus character can only be in the first position, and the period character can only appear once.{\*\bkmkend values-in-conditions}} +\par \pard\plain \s4\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\i\dbch\af9{\loch +{\*\bkmkstart values-in-actions}Values in Actions} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +A }{\rtlch\ai \ltrch\loch\i\loch +value}{\loch + in an action is one of} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls10 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +symbolic-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls10 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +arithmetic-value} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls10 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +number} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +where }{\rtlch\ai \ltrch\loch\i\loch +arithmetic-value}{\loch + is:} +\par \pard\plain \s167\loch\ql\widctlpar\sb36\sa36\ltrpar{\listtext\pard\plain \u8226\'95\tab}\ilvl0\ls11 \li720\ri0\lin720\rin0\fi-480{\rtlch\ai \ltrch\loch\i\loch +property}{\loch + }{\rtlch\ai \ltrch\loch\i\loch +operator}{\loch + }{\rtlch\ai \ltrch\loch\i\loch +numeric-value} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +and }{\rtlch\ai \ltrch\loch\i\loch +operator}{\loch + is one of the simple arithmetic operators \u8216\'91+\u8217\'92, \u8216\'91-\u8217\'92, \u8217\'92*\u8217\'92 and \u8216\'91/\u8217\'92.{\*\bkmkend grammar}{\*\bkmkend values-in-actions}} +\par \pard\plain \s3\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\b\dbch\af9{\loch +{\*\bkmkstart shorthand}Shorthand} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +{\*\bkmkstart shorthand}Note that \u8216\'91\u8230\'85neighbours are\u8230\'85\u8217\'92 is equivalent to \u8216\'91\u8230\'85neighbours have state equal to\u8230\'85\u8217\'92, and \u8216\'91some neighbours\u8230\'85\u8217\'92 is equivalent to \u8216\'91more than 0 neighbours\u8230\'85\u8217\'92{\*\bkmkend shorthand}} +\par \pard\plain \s3\rtlch\af9\afs24\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs24\b\dbch\af9{\loch +{\*\bkmkstart roadmap}Roadmap} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +The existing parser, }{\rtlch\ai \ltrch\loch\i\loch +mw-parser.core}{\loch +, works but is not well written. A much better parser which does not yet completely work, }{\rtlch\ai \ltrch\loch\i\loch +mw-parser.insta}{\loch +, is also included for the adventurous.} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +I intend to replace }{\rtlch\ai \ltrch\loch\i\loch +mw-parser.core}{\loch + with }{\rtlch\ai \ltrch\loch\i\loch +mw-parser.insta}{\loch + as soon as }{\rtlch\ai \ltrch\loch\i\loch +mw-parser.insta}{\loch + correctly parses all the test rules.{\*\bkmkend usage}{\*\bkmkend roadmap}} +\par \pard\plain \s2\rtlch\af9\afs28\ab \ltrch\hich\af6\loch\ql\keep\widctlpar\sb200\sa0\keepn\ltrpar\cf18\f6\fs28\b\dbch\af9{\loch +{\*\bkmkstart license}License} +\par \pard\plain \s166\loch\ql\widctlpar\sb180\sa180\ltrpar{\loch +Copyright \u169\'a9 2014 }{{\field{\*\fldinst HYPERLINK "mailto:simon@journeyman.cc" }{\fldrslt {\loch\loch\cf18\loch +Simon Brooke}}}} +\par \pard\plain \s162\loch\ql\widctlpar\sb180\sa180\ltrpar\sb180\sa180{\loch +Distributed under the terms of the }{{\field{\*\fldinst HYPERLINK "http://www.gnu.org/licenses/gpl-2.0.html" }{\fldrslt {\loch\loch\cf18\loch +GNU General Public License v2}}}{\*\bkmkend mw-parser}{\*\bkmkend license}} +\par } \ No newline at end of file diff --git a/resources/heightmaps/barra.png b/resources/heightmaps/barra.png new file mode 100644 index 0000000..b5f0799 Binary files /dev/null and b/resources/heightmaps/barra.png differ diff --git a/resources/heightmaps/barra.xcf b/resources/heightmaps/barra.xcf new file mode 100644 index 0000000..766fe52 Binary files /dev/null and b/resources/heightmaps/barra.xcf differ diff --git a/resources/heightmaps/great_britain_and_ireland_med.png b/resources/heightmaps/great_britain_and_ireland_med.png new file mode 100644 index 0000000..558e79b Binary files /dev/null and b/resources/heightmaps/great_britain_and_ireland_med.png differ diff --git a/resources/heightmaps/great_britain_and_ireland_original.png b/resources/heightmaps/great_britain_and_ireland_original.png new file mode 100644 index 0000000..a3dd035 Binary files /dev/null and b/resources/heightmaps/great_britain_and_ireland_original.png differ diff --git a/resources/heightmaps/great_britain_and_ireland_small.png b/resources/heightmaps/great_britain_and_ireland_small.png new file mode 100644 index 0000000..c6777f7 Binary files /dev/null and b/resources/heightmaps/great_britain_and_ireland_small.png differ diff --git a/resources/heightmaps/isle_of_man.png b/resources/heightmaps/isle_of_man.png new file mode 100644 index 0000000..7de05e9 Binary files /dev/null and b/resources/heightmaps/isle_of_man.png differ diff --git a/resources/heightmaps/life_gosperglidergun.png b/resources/heightmaps/life_gosperglidergun.png new file mode 100644 index 0000000..c11c56c Binary files /dev/null and b/resources/heightmaps/life_gosperglidergun.png differ diff --git a/resources/heightmaps/mgi_med.png b/resources/heightmaps/mgi_med.png new file mode 100644 index 0000000..cb4e875 Binary files /dev/null and b/resources/heightmaps/mgi_med.png differ diff --git a/resources/heightmaps/small_hill.png b/resources/heightmaps/small_hill.png new file mode 100644 index 0000000..8be86e4 Binary files /dev/null and b/resources/heightmaps/small_hill.png differ diff --git a/resources/heightmaps/test.heightmap.png b/resources/heightmaps/test.heightmap.png new file mode 100644 index 0000000..0065257 Binary files /dev/null and b/resources/heightmaps/test.heightmap.png differ diff --git a/resources/heightmaps/test.heightmap.xcf b/resources/heightmaps/test.heightmap.xcf new file mode 100644 index 0000000..0bfb048 Binary files /dev/null and b/resources/heightmaps/test.heightmap.xcf differ diff --git a/resources/init-state/world.edn b/resources/init-state/world.edn new file mode 100644 index 0000000..590dddb --- /dev/null +++ b/resources/init-state/world.edn @@ -0,0 +1,7 @@ +[[{:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 10, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 0, :altitude 13} {:y 0, :state :scrub, :x 1, :altitude 20, :gradient 28, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 0, :state :scrub, :x 2, :altitude 29, :gradient 35, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 0, :state :grassland, :x 3, :altitude 39, :gradient 43, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :state :grassland, :x 4, :altitude 51, :gradient 48, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 51, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 5, :altitude 64} {:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 46, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 6, :altitude 73} {:y 0, :state :scrub, :x 7, :altitude 82, :gradient 44, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 0, :state :grassland, :x 8, :altitude 90, :gradient 40, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :state :scrub, :x 9, :altitude 91, :gradient 38, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 40, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 10, :altitude 91} {:y 0, :state :grassland, :x 11, :altitude 88, :gradient 47, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :state :scrub, :x 12, :altitude 81, :gradient 55, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 53, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 13, :altitude 69} {:y 0, :state :grassland, :x 14, :altitude 60, :gradient 54, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :state :grassland, :x 15, :altitude 47, :gradient 51, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 46, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 16, :altitude 34} {:y 0, :state :grassland, :x 17, :altitude 23, :gradient 41, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 0, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 32, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 18, :altitude 12} {:y 0, :state :water, :x 19, :altitude 6, :gradient 12, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10}] [{:y 1, :state :grassland, :x 0, :altitude 19, :gradient 28, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 1, :state :grassland, :x 1, :altitude 29, :gradient 42, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 1, :state :scrub, :x 2, :altitude 41, :gradient 52, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 62, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 3, :altitude 55} + +{:y 1, :state :forest, :x 4, :altitude 72, :gradient 74, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 76, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 5, :altitude 87} {:y 1, :state :scrub, :x 6, :altitude 102, :gradient 69, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 69, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 7, :altitude 110} + + + +{:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 67, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 4 when in state :forest", :x 8, :altitude 117} {:y 1, :state :heath, :x 9, :altitude 122, :gradient 62, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 1, :state :grassland, :x 10, :altitude 128, :gradient 64, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 1, :state :heath, :x 11, :altitude 124, :gradient 71, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 1, :state :forest, :x 12, :altitude 113, :gradient 82, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 79, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 13, :altitude 101} {:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 82, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 6 when in state :forest", :x 14, :altitude 85} {:y 1, :state :grassland, :x 15, :altitude 69, :gradient 78, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 1, :state :grassland, :x 16, :altitude 53, :gradient 69, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 1, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 62, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 17, :altitude 38} {:y 1, :state :scrub, :x 18, :altitude 24, :gradient 48, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 1, :state :grassland, :x 19, :altitude 15, :gradient 30, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10}] [{:y 2, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 28, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 0, :altitude 27} {:y 2, :state :grassland, :x 1, :altitude 41, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :scrub, :x 2, :altitude 55, :gradient 62, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 2, :state :scrub, :x 3, :altitude 72, :gradient 70, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 2, :state :scrub, :x 4, :altitude 91, :gradient 72, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 2, :state :forest, :x 5, :altitude 113, :gradient 70, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 2, :state :grassland, :x 6, :altitude 127, :gradient 63, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 7, :altitude 133, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 8, :altitude 142, :gradient 57, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 9, :altitude 149, :gradient 50, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :heath, :x 10, :altitude 152, :gradient 45, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 2, :state :grassland, :x 11, :altitude 151, :gradient 54, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 12, :altitude 139, :gradient 64, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 13, :altitude 129, :gradient 73, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 81, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 14, :altitude 112} {:y 2, :state :grassland, :x 15, :altitude 92, :gradient 85, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 16, :altitude 74, :gradient 82, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 17, :altitude 54, :gradient 73, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 18, :altitude 36, :gradient 56, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 2, :state :grassland, :x 19, :altitude 23, :gradient 36, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10}] [{:y 3, :state :grassland, :x 0, :altitude 33, :gradient 26, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :grassland, :x 1, :altitude 47, :gradient 48, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :grassland, :x 2, :altitude 68, :gradient 59, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :scrub, :x 3, :altitude 91, :gradient 68, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 3, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 64, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 4, :altitude 111} {:y 3, :state :grassland, :x 5, :altitude 127, :gradient 57, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :heath, :x 6, :altitude 142, :gradient 48, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 3, :state :grassland, :x 7, :altitude 150, :gradient 44, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :heath, :x 8, :altitude 160, :gradient 59, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 3, :state :heath, :x 9, :altitude 167, :gradient 56, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 3, :state :heath, :x 10, :altitude 167, :gradient 49, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 3, :state :heath, :x 11, :altitude 165, :gradient 59, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 3, :state :grassland, :x 12, :altitude 158, :gradient 68, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :grassland, :x 13, :altitude 150, :gradient 63, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :grassland, :x 14, :altitude 138, :gradient 71, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :grassland, :x 15, :altitude 120, :gradient 78, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :scrub, :x 16, :altitude 97, :gradient 84, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 3, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 80, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 17, :altitude 71} {:y 3, :state :grassland, :x 18, :altitude 51, :gradient 66, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 3, :state :scrub, :x 19, :altitude 33, :gradient 42, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10}] [{:y 4, :state :grassland, :x 0, :altitude 36, :gradient 24, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 48, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 1, :altitude 53} {:y 4, :state :grassland, :x 2, :altitude 75, :gradient 54, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 55, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 3, :altitude 100} {:y 4, :state :grassland, :x 4, :altitude 123, :gradient 45, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :heath, :x 5, :altitude 136, :gradient 37, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 4, :state :grassland, :x 6, :altitude 148, :gradient 34, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :grassland, :x 7, :altitude 161, :gradient 31, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :grassland, :x 8, :altitude 171, :gradient 57, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :grassland, :x 9, :altitude 192, :gradient 62, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :grassland, :x 10, :altitude 198, :gradient 57, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :grassland, :x 11, :altitude 197, :gradient 64, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :heath, :x 12, :altitude 175, :gradient 64, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 4, :state :heath, :x 13, :altitude 163, :gradient 50, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 4, :state :heath, :x 14, :altitude 152, :gradient 53, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 4, :state :grassland, :x 15, :altitude 138, :gradient 66, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :state :scrub, :x 16, :altitude 116, :gradient 78, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 4, :state :grassland, :x 17, :altitude 89, :gradient 74, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 4, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 68, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 18, :altitude 65} {:y 4, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 43, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 19, :altitude 45}] [{:y 5, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 21, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 0, :altitude 37} {:y 5, :state :scrub, :x 1, :altitude 57, :gradient 45, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 5, :state :grassland, :x 2, :altitude 81, :gradient 48, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 5, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 49, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 3, :altitude 101} {:y 5, :state :heath, :x 4, :altitude 122, :gradient 45, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 5, :state :grassland, :x 5, :altitude 135, :gradient 34, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 5, :state :heath, :x 6, :altitude 147, :gradient 29, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 5, :state :heath, :x 7, :altitude 161, :gradient 29, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 5, :state :heath, :x 8, :altitude 173, :gradient 48, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 5, :state :snow, :x 9, :altitude 207, :gradient 53, :rule "if state is new and altitude is more than 200 then state should be snow", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (> (:altitude cell) 200)) (merge cell {:state :snow}))), :generation 10} {:y 5, :state :snow, :x 10, :altitude 222, :gradient 28, :rule "if state is new and altitude is more than 200 then state should be snow", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (> (:altitude cell) 200)) (merge cell {:state :snow}))), :generation 10} {:y 5, :state :snow, :x 11, :altitude 214, :gradient 47, :rule "if state is new and altitude is more than 200 then state should be snow", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (> (:altitude cell) 200)) (merge cell {:state :snow}))), :generation 10} {:y 5, :state :grassland, :x 12, :altitude 188, :gradient 52, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 5, :state :grassland, :x 13, :altitude 173, :gradient 36, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 5, :state :grassland, :x 14, :altitude 163, :gradient 37, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 5, :state :heath, :x 15, :altitude 149, :gradient 49, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 5, :state :heath, :x 16, :altitude 125, :gradient 63, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 5, :state :grassland, :x 17, :altitude 101, :gradient 68, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 5, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 63, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 18, :altitude 76} {:y 5, :state :heath, :x 19, :altitude 53, :gradient 38, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10}] [{:y 6, :state :heath, :x 0, :altitude 36, :gradient 27, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 6, :state :scrub, :x 1, :altitude 53, :gradient 51, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 6, :state :scrub, :x 2, :altitude 74, :gradient 55, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 6, :state :forest, :x 3, :altitude 91, :gradient 57, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 6, :state :scrub, :x 4, :altitude 114, :gradient 52, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 6, :state :grassland, :x 5, :altitude 132, :gradient 46, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 6, :state :heath, :x 6, :altitude 144, :gradient 42, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 6, :state :grassland, :x 7, :altitude 159, :gradient 39, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 6, :state :heath, :x 8, :altitude 169, :gradient 59, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 6, :state :snow, :x 9, :altitude 204, :gradient 64, :rule "if state is new and altitude is more than 200 then state should be snow", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (> (:altitude cell) 200)) (merge cell {:state :snow}))), :generation 10} {:y 6, :state :snow, :x 10, :altitude 220, :gradient 40, :rule "if state is new and altitude is more than 200 then state should be snow", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (> (:altitude cell) 200)) (merge cell {:state :snow}))), :generation 10} {:y 6, :state :snow, :x 11, :altitude 215, :gradient 38, :rule "if state is new and altitude is more than 200 then state should be snow", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (> (:altitude cell) 200)) (merge cell {:state :snow}))), :generation 10} {:y 6, :state :heath, :x 12, :altitude 187, :gradient 43, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 6, :state :heath, :x 13, :altitude 175, :gradient 25, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 6, :state :grassland, :x 14, :altitude 165, :gradient 26, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 6, :state :grassland, :x 15, :altitude 152, :gradient 41, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 6, :state :grassland, :x 16, :altitude 133, :gradient 52, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 6, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 58, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 6 when in state :forest", :x 17, :altitude 108} {:y 6, :state :grassland, :x 18, :altitude 83, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 6, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 36, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 19, :altitude 59}] [{:y 7, :state :forest, :x 0, :altitude 30, :gradient 29, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 7, :state :grassland, :x 1, :altitude 46, :gradient 50, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :forest, :x 2, :altitude 65, :gradient 54, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 7, :state :grassland, :x 3, :altitude 83, :gradient 62, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :grassland, :x 4, :altitude 101, :gradient 55, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :scrub, :x 5, :altitude 119, :gradient 58, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 7, :state :heath, :x 6, :altitude 134, :gradient 59, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :grassland, :x 7, :altitude 148, :gradient 50, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :heath, :x 8, :altitude 158, :gradient 70, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :heath, :x 9, :altitude 182, :gradient 76, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :heath, :x 10, :altitude 192, :gradient 65, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :heath, :x 11, :altitude 195, :gradient 59, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :heath, :x 12, :altitude 184, :gradient 50, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :grassland, :x 13, :altitude 172, :gradient 28, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :grassland, :x 14, :altitude 166, :gradient 25, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :heath, :x 15, :altitude 153, :gradient 33, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 7, :state :grassland, :x 16, :altitude 134, :gradient 45, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 7, :state :scrub, :x 17, :altitude 111, :gradient 53, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 7, :state :scrub, :x 18, :altitude 89, :gradient 53, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 7, :state :scrub, :x 19, :altitude 63, :gradient 30, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10}] [{:y 8, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 29, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 0, :altitude 24} {:y 8, :state :scrub, :x 1, :altitude 37, :gradient 48, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 8, :state :forest, :x 2, :altitude 52, :gradient 55, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 8, :state :grassland, :x 3, :altitude 77, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :scrub, :x 4, :altitude 86, :gradient 65, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 8, :state :grassland, :x 5, :altitude 100, :gradient 68, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :scrub, :x 6, :altitude 119, :gradient 59, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 8, :state :grassland, :x 7, :altitude 134, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :heath, :x 8, :altitude 144, :gradient 65, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 8, :state :heath, :x 9, :altitude 155, :gradient 69, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 8, :state :heath, :x 10, :altitude 161, :gradient 59, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 8, :state :grassland, :x 11, :altitude 166, :gradient 51, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :grassland, :x 12, :altitude 166, :gradient 43, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :heath, :x 13, :altitude 165, :gradient 33, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 8, :state :grassland, :x 14, :altitude 159, :gradient 28, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :heath, :x 15, :altitude 150, :gradient 32, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 8, :state :heath, :x 16, :altitude 136, :gradient 43, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 8, :state :grassland, :x 17, :altitude 112, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :state :grassland, :x 18, :altitude 89, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 8, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 26, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 19, :altitude 63}] [{:y 9, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 27, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 0, :altitude 17} {:y 9, :state :scrub, :x 1, :altitude 28, :gradient 42, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 9, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 58, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 2, :altitude 43} {:y 9, :state :grassland, :x 3, :altitude 54, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :grassland, :x 4, :altitude 66, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :forest, :x 5, :altitude 89, :gradient 59, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 9, :state :grassland, :x 6, :altitude 109, :gradient 57, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :grassland, :x 7, :altitude 117, :gradient 49, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :heath, :x 8, :altitude 123, :gradient 60, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :grassland, :x 9, :altitude 136, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :grassland, :x 10, :altitude 144, :gradient 47, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :heath, :x 11, :altitude 152, :gradient 44, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :heath, :x 12, :altitude 155, :gradient 30, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :heath, :x 13, :altitude 154, :gradient 25, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :heath, :x 14, :altitude 151, :gradient 26, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :heath, :x 15, :altitude 144, :gradient 26, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :heath, :x 16, :altitude 135, :gradient 41, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 9, :state :grassland, :x 17, :altitude 110, :gradient 50, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :grassland, :x 18, :altitude 87, :gradient 51, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 9, :state :grassland, :x 19, :altitude 63, :gradient 28, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10}] [{:y 10, :state :grassland, :x 0, :altitude 10, :gradient 22, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 37, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 6 when in state :forest", :x 1, :altitude 19} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 42, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 4 when in state :forest", :x 2, :altitude 37} {:y 10, :state :grassland, :x 3, :altitude 51, :gradient 41, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 46, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 5 when in state :forest", :x 4, :altitude 60} {:y 10, :state :forest, :x 5, :altitude 77, :gradient 49, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 10, :state :scrub, :x 6, :altitude 96, :gradient 40, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 42, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 7, :altitude 95} {:y 10, :state :forest, :x 8, :altitude 103, :gradient 55, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 10, :state :grassland, :x 9, :altitude 119, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :state :grassland, :x 10, :altitude 122, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :state :heath, :x 11, :altitude 136, :gradient 55, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 10, :state :heath, :x 12, :altitude 141, :gradient 40, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 10, :state :heath, :x 13, :altitude 145, :gradient 29, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 10, :state :grassland, :x 14, :altitude 147, :gradient 19, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :state :grassland, :x 15, :altitude 139, :gradient 21, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :state :grassland, :x 16, :altitude 133, :gradient 35, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 49, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 17, :altitude 109} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 49, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 18, :altitude 86} {:y 10, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 24, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 19, :altitude 61}] [{:y 11, :state :water, :x 0, :altitude 6, :gradient 16, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 11, :state :scrub, :x 1, :altitude 12, :gradient 34, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 11, :state :grassland, :x 2, :altitude 25, :gradient 39, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :state :forest, :x 3, :altitude 43, :gradient 39, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 11, :state :grassland, :x 4, :altitude 60, :gradient 45, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 50, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 5, :altitude 80} {:y 11, :state :scrub, :x 6, :altitude 84, :gradient 45, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 11, :state :grassland, :x 7, :altitude 81, :gradient 46, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :state :grassland, :x 8, :altitude 86, :gradient 59, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :state :grassland, :x 9, :altitude 94, :gradient 45, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :state :forest, :x 10, :altitude 100, :gradient 59, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 11, :state :grassland, :x 11, :altitude 115, :gradient 55, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :state :heath, :x 12, :altitude 126, :gradient 39, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 11, :state :heath, :x 13, :altitude 135, :gradient 26, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 11, :state :grassland, :x 14, :altitude 141, :gradient 18, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :state :heath, :x 15, :altitude 136, :gradient 22, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 11, :state :grassland, :x 16, :altitude 130, :gradient 30, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 11, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 47, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 6 when in state :forest", :x 17, :altitude 110} {:y 11, :state :scrub, :x 18, :altitude 86, :gradient 51, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 11, :state :scrub, :x 19, :altitude 63, :gradient 26, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10}] [{:y 12, :state :water, :x 0, :altitude 3, :gradient 15, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 12, :state :scrub, :x 1, :altitude 17, :gradient 23, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 12, :state :grassland, :x 2, :altitude 21, :gradient 34, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 12, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 48, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 3, :altitude 35} {:y 12, :state :grassland, :x 4, :altitude 46, :gradient 61, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 12, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 54, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 5, :altitude 51} {:y 12, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 54, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 6, :altitude 57} {:y 12, :state :heath, :x 7, :altitude 60, :gradient 46, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 12, :state :scrub, :x 8, :altitude 80, :gradient 47, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 12, :state :grassland, :x 9, :altitude 77, :gradient 31, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 12, :state :heath, :x 10, :altitude 86, :gradient 46, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 12, :state :grassland, :x 11, :altitude 106, :gradient 40, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 12, :state :heath, :x 12, :altitude 121, :gradient 29, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 12, :state :grassland, :x 13, :altitude 129, :gradient 20, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 12, :state :heath, :x 14, :altitude 138, :gradient 12, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 12, :state :heath, :x 15, :altitude 136, :gradient 16, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 12, :state :heath, :x 16, :altitude 125, :gradient 27, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 12, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 44, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 17, :altitude 112} {:y 12, :state :forest, :x 18, :altitude 87, :gradient 52, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 12, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 29, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 19, :altitude 64}] [{:y 13, :state :water, :x 0, :altitude 2, :gradient 16, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 13, :state :water, :x 1, :altitude 9, :gradient 20, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 13, :state :grassland, :x 2, :altitude 12, :gradient 30, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :grassland, :x 3, :altitude 19, :gradient 37, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :forest, :x 4, :altitude 44, :gradient 42, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 13, :state :grassland, :x 5, :altitude 30, :gradient 42, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :scrub, :x 6, :altitude 40, :gradient 45, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 13, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 41, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 7, :altitude 47} {:y 13, :state :heath, :x 8, :altitude 73, :gradient 42, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 13, :state :grassland, :x 9, :altitude 69, :gradient 36, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 56, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 7 when in state :forest", :x 10, :altitude 86} {:y 13, :state :grassland, :x 11, :altitude 111, :gradient 39, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :heath, :x 12, :altitude 121, :gradient 29, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 13, :state :heath, :x 13, :altitude 133, :gradient 19, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 13, :state :grassland, :x 14, :altitude 136, :gradient 11, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :heath, :x 15, :altitude 137, :gradient 15, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 13, :state :grassland, :x 16, :altitude 129, :gradient 28, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :scrub, :x 17, :altitude 115, :gradient 44, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 13, :state :grassland, :x 18, :altitude 92, :gradient 51, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 13, :state :grassland, :x 19, :altitude 68, :gradient 32, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10}] [{:y 14, :state :water, :x 0, :altitude 1, :gradient 8, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 14, :state :water, :x 1, :altitude 5, :gradient 11, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 14, :state :water, :x 2, :altitude 9, :gradient 18, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 14, :state :water, :x 3, :altitude 9, :gradient 38, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 14, :state :scrub, :x 4, :altitude 24, :gradient 38, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 14, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 31, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 4 when in state :forest", :x 5, :altitude 15} {:y 14, :state :grassland, :x 6, :altitude 39, :gradient 36, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 14, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 43, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 4 when in state :forest", :x 7, :altitude 49} {:y 14, :state :scrub, :x 8, :altitude 68, :gradient 66, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 14, :state :grassland, :x 9, :altitude 89, :gradient 56, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 14, :state :grassland, :x 10, :altitude 104, :gradient 58, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 14, :state :heath, :x 11, :altitude 125, :gradient 46, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 14, :state :grassland, :x 12, :altitude 125, :gradient 31, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 14, :state :heath, :x 13, :altitude 135, :gradient 26, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 14, :state :heath, :x 14, :altitude 140, :gradient 15, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 14, :state :heath, :x 15, :altitude 140, :gradient 19, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 14, :state :heath, :x 16, :altitude 131, :gradient 33, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 14, :state :grassland, :x 17, :altitude 115, :gradient 43, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 14, :state :heath, :x 18, :altitude 96, :gradient 53, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 14, :state :forest, :x 19, :altitude 74, :gradient 32, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10}] [{:y 15, :state :water, :x 0, :altitude 1, :gradient 4, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 15, :state :water, :x 1, :altitude 1, :gradient 8, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 15, :state :water, :x 2, :altitude 7, :gradient 8, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 15, :state :water, :x 3, :altitude 6, :gradient 19, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 15, :state :grassland, :x 4, :altitude 13, :gradient 18, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :state :grassland, :x 5, :altitude 13, :gradient 31, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :state :scrub, :x 6, :altitude 30, :gradient 48, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 15, :state :grassland, :x 7, :altitude 46, :gradient 55, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :state :forest, :x 8, :altitude 65, :gradient 66, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 15, :state :heath, :x 9, :altitude 112, :gradient 60, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 15, :state :heath, :x 10, :altitude 121, :gradient 38, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 15, :state :heath, :x 11, :altitude 127, :gradient 32, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 15, :state :heath, :x 12, :altitude 132, :gradient 22, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 15, :state :heath, :x 13, :altitude 142, :gradient 28, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 15, :state :heath, :x 14, :altitude 147, :gradient 18, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 15, :state :grassland, :x 15, :altitude 148, :gradient 22, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :state :grassland, :x 16, :altitude 135, :gradient 37, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :state :grassland, :x 17, :altitude 121, :gradient 41, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :state :grassland, :x 18, :altitude 100, :gradient 47, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 15, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 26, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 19, :altitude 76}] [{:y 16, :state :water, :x 0, :altitude 1, :gradient 2, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 16, :state :water, :x 1, :altitude 1, :gradient 6, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 16, :state :water, :x 2, :altitude 5, :gradient 6, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 16, :state :water, :x 3, :altitude 7, :gradient 10, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 16, :state :water, :x 4, :altitude 8, :gradient 10, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 16, :state :water, :x 5, :altitude 9, :gradient 25, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 16, :state :scrub, :x 6, :altitude 28, :gradient 48, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 16, :state :scrub, :x 7, :altitude 57, :gradient 61, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 16, :state :scrub, :x 8, :altitude 83, :gradient 66, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 16, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 60, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 9, :altitude 111} {:y 16, :state :grassland, :x 10, :altitude 125, :gradient 25, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 16, :state :grassland, :x 11, :altitude 125, :gradient 21, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 16, :state :heath, :x 12, :altitude 136, :gradient 27, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 16, :state :heath, :x 13, :altitude 147, :gradient 21, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 16, :state :heath, :x 14, :altitude 153, :gradient 10, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 16, :state :grassland, :x 15, :altitude 152, :gradient 18, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 16, :state :heath, :x 16, :altitude 137, :gradient 34, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 16, :state :heath, :x 17, :altitude 121, :gradient 41, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 16, :state :grassland, :x 18, :altitude 99, :gradient 51, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 16, :state :grassland, :x 19, :altitude 75, :gradient 30, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10}] [{:y 17, :state :water, :x 0, :altitude 1, :gradient 2, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 17, :state :water, :x 1, :altitude 3, :gradient 4, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 17, :state :water, :x 2, :altitude 3, :gradient 6, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 17, :state :water, :x 3, :altitude 3, :gradient 7, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 17, :state :water, :x 4, :altitude 5, :gradient 8, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 17, :state :grassland, :x 5, :altitude 10, :gradient 23, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 17, :state :grassland, :x 6, :altitude 24, :gradient 48, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 17, :state :grassland, :x 7, :altitude 46, :gradient 63, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 17, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 69, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 8, :altitude 85} {:y 17, :state :scrub, :x 9, :altitude 102, :gradient 52, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 17, :state :scrub, :x 10, :altitude 116, :gradient 38, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 17, :state :heath, :x 11, :altitude 123, :gradient 35, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 17, :state :heath, :x 12, :altitude 137, :gradient 29, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 17, :state :heath, :x 13, :altitude 150, :gradient 19, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 17, :state :heath, :x 14, :altitude 152, :gradient 13, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 17, :state :heath, :x 15, :altitude 148, :gradient 24, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 17, :state :heath, :x 16, :altitude 138, :gradient 41, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 17, :state :scrub, :x 17, :altitude 118, :gradient 50, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 17, :state :scrub, :x 18, :altitude 97, :gradient 55, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 17, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 33, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 6 when in state :forest", :x 19, :altitude 70}] [{:y 18, :state :water, :x 0, :altitude 1, :gradient 2, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 18, :state :water, :x 1, :altitude 1, :gradient 2, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 18, :state :water, :x 2, :altitude 1, :gradient 2, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 18, :state :water, :x 3, :altitude 3, :gradient 4, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 18, :state :water, :x 4, :altitude 5, :gradient 10, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 18, :state :grassland, :x 5, :altitude 11, :gradient 20, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 36, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 6 when in state :forest", :x 6, :altitude 22} {:y 18, :state :scrub, :x 7, :altitude 42, :gradient 64, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 18, :state :forest, :x 8, :altitude 73, :gradient 68, :rule "if state is scrub then 1 chance in 5 state should be forest", :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :generation 10} {:y 18, :state :grassland, :x 9, :altitude 87, :gradient 57, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 45, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 4 when in state :forest", :x 10, :altitude 102} {:y 18, :state :grassland, :x 11, :altitude 121, :gradient 42, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :state :grassland, :x 12, :altitude 134, :gradient 38, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :state :grassland, :x 13, :altitude 145, :gradient 26, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :state :heath, :x 14, :altitude 145, :gradient 24, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 18, :state :heath, :x 15, :altitude 140, :gradient 34, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 18, :state :grassland, :x 16, :altitude 129, :gradient 47, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :state :grassland, :x 17, :altitude 111, :gradient 59, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :state :grassland, :x 18, :altitude 88, :gradient 63, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 18, :state :scrub, :x 19, :altitude 66, :gradient 42, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10}] [{:y 19, :state :water, :x 0, :altitude 1, :gradient 0, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 19, :state :water, :x 1, :altitude 1, :gradient 0, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 19, :state :water, :x 2, :altitude 1, :gradient 2, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 19, :state :water, :x 3, :altitude 1, :gradient 4, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 19, :state :water, :x 4, :altitude 4, :gradient 10, :rule "if state is new and altitude is less than 10 then state should be water", :lisp (fn [cell world] (when (and (= (:state cell) (or (:new cell) :new)) (< (:altitude cell) 10)) (merge cell {:state :water}))), :generation 10} {:y 19, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 18, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 9 when in state :forest", :x 5, :altitude 11} {:y 19, :state :scrub, :x 6, :altitude 21, :gradient 31, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 19, :state :grassland, :x 7, :altitude 34, :gradient 52, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 19, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 53, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 8, :altitude 59} {:y 19, :generation 9, :lisp (fn [cell world] (when (= (:state cell) (or (:scrub cell) :scrub)) (if (< (rand 5) 1) (merge cell {:state :forest})))), :rule "if state is scrub then 1 chance in 5 state should be forest", :state :error, :gradient 43, :stacktrace ("clojure.lang.Numbers.ops(Numbers.java:1095)" "clojure.lang.Numbers.gt(Numbers.java:261)" "clojure.lang.Numbers.gt(Numbers.java:3967)" "mw_desktop.core$eval9735$fn__9736.invoke(492c9e7d63cf6a02a8ff13d60211a48a8b57468b-init.clj:1)" "clojure.lang.AFn.applyToHelper(AFn.java:156)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.core$apply_rule.invokeStatic(core.clj:61)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rule.invokeStatic(core.clj:63)" "mw_engine.core$apply_rule.invoke(core.clj:52)" "mw_engine.core$apply_rules$fn__7798.invoke(core.clj:75)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core$filter$fn__5962.invoke(core.clj:2826)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.LazySeq.first(LazySeq.java:73)" "clojure.lang.RT.first(RT.java:692)" "clojure.core$first__5449.invokeStatic(core.clj:55)" "clojure.core$first__5449.invoke(core.clj:55)" "mw_engine.core$apply_rules.invokeStatic(core.clj:75)" "mw_engine.core$apply_rules.invoke(core.clj:68)" "mw_engine.core$transform_cell.invokeStatic(core.clj:88)" "mw_engine.core$transform_cell.invoke(core.clj:82)" "clojure.lang.AFn.applyToHelper(AFn.java:160)" "clojure.lang.AFn.applyTo(AFn.java:144)" "clojure.core$apply.invokeStatic(core.clj:667)" "clojure.core$apply.invoke(core.clj:662)" "mw_engine.utils$map_world$fn__3446$fn__3447.invoke(utils.clj:113)" "clojure.core$map$fn__5935.invoke(core.clj:2770)" "clojure.lang.LazySeq.sval(LazySeq.java:42)" "clojure.lang.LazySeq.seq(LazySeq.java:51)" "clojure.lang.RT.seq(RT.java:535)" "clojure.core$seq__5467.invokeStatic(core.clj:139)" "clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)" "clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)" "clojure.core.protocols$fn__8236.invoke(protocols.clj:75)" "clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)" "clojure.core$reduce.invokeStatic(core.clj:6886)" "clojure.core$into.invokeStatic(core.clj:6958)" "clojure.core$into.invoke(core.clj:6950)" "mw_engine.utils$map_world$fn__3446.invoke(utils.clj:112)" "clojure.core$pmap$fn__8552$fn__8553.invoke(core.clj:7089)" "clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)" "clojure.lang.AFn.call(AFn.java:18)" "java.util.concurrent.FutureTask.run(FutureTask.java:266)" "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)" "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)" "java.lang.Thread.run(Thread.java:748)"), :error "null at generation 8 when in state :forest", :x 9, :altitude 78} {:y 19, :state :grassland, :x 10, :altitude 95, :gradient 43, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 19, :state :scrub, :x 11, :altitude 112, :gradient 39, :rule "if state is heath and altitude is less than 120 then state should be scrub", :lisp (fn [cell world] (when (and (= (:state cell) (or (:heath cell) :heath)) (< (:altitude cell) 120)) (merge cell {:state :scrub}))), :generation 10} {:y 19, :state :heath, :x 12, :altitude 126, :gradient 33, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 19, :state :heath, :x 13, :altitude 134, :gradient 19, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 19, :state :grassland, :x 14, :altitude 134, :gradient 17, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 19, :state :heath, :x 15, :altitude 128, :gradient 27, :rule "if state is grassland then 1 chance in 10 state should be heath", :lisp (fn [cell world] (when (= (:state cell) (or (:grassland cell) :grassland)) (if (< (rand 10) 1) (merge cell {:state :heath})))), :generation 10} {:y 19, :state :grassland, :x 16, :altitude 118, :gradient 39, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 19, :state :grassland, :x 17, :altitude 101, :gradient 50, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 19, :state :grassland, :x 18, :altitude 79, :gradient 56, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10} {:y 19, :state :grassland, :x 19, :altitude 55, :gradient 22, :rule "if state is new then state should be grassland", :lisp (fn [cell world] (when (= (:state cell) (or (:new cell) :new)) (merge cell {:state :grassland}))), :generation 10}]] \ No newline at end of file diff --git a/resources/rulesets/basic.txt b/resources/rulesets/basic.txt new file mode 100644 index 0000000..d7f2d5f --- /dev/null +++ b/resources/rulesets/basic.txt @@ -0,0 +1,59 @@ +## Basic ruleset which just grows trees + +;; This ruleset is not very interesting in itself, but is useful as a starting +;; point from which to build more interesting rulesets. + +## Vegetation rules +;; rules which populate the world with plants + +;; Occasionally, passing birds plant tree seeds into grassland + +if state is grassland then 1 chance in 10 state should be heath + +;; heath below the treeline grows gradually into forest + +if state is heath and altitude is less than 120 then state should be scrub +if state is scrub then 1 chance in 5 state should be forest + +;; Forest on fertile land grows to climax + +if state is forest and fertility is more than 5 and altitude is less than 70 then state should be climax + +;; Climax forest occasionally catches fire (e.g. lightning strikes) + +if state is climax then 1 chance in 500 state should be fire + +;; Climax forest neighbouring fires is likely to catch fire +if state is climax and some neighbours are fire then 1 chance in 3 state should be fire + +;; After fire we get waste + +if state is fire then state should be waste + +;; And after waste we get pioneer species; if there's a woodland seed +;; source, it's going to be heath, otherwise grassland. + +if state is waste and some neighbours are scrub then state should be heath +if state is waste and some neighbours are forest then state should be heath +if state is waste and some neighbours are climax then state should be heath +if state is waste then state should be grassland + +## Potential blockers + +;; Forest increases soil fertility. +if state is in forest or climax then fertility should be fertility + 1 + + +## Initialisation rules + +;; Rules which deal with state 'new' will waste less time if they're near the +;; end of the file + +;; below the waterline we have water. +if state is new and altitude is less than 10 then state should be water + +;; above the snowline we have snow. +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 diff --git a/resources/rulesets/conway_life.txt b/resources/rulesets/conway_life.txt new file mode 100644 index 0000000..6ca12fe --- /dev/null +++ b/resources/rulesets/conway_life.txt @@ -0,0 +1,39 @@ +# Conway's Game of Life is the classic cellular automaton. + +;; see http://en.wikipedia.org/wiki/Conway's_Game_of_Life + +;; This ruleset works with any strictly black and white map, but the maps which +;; are designed to work with it have names starting 'life'. + +;; The universe of the Game of Life is an infinite two-dimensional orthogonal +;; grid of square cells, each of which is in one of two possible states, alive +;; or dead, represented in this ruleset by 'black' and 'white' respectively. +;; Every cell interacts with its eight neighbours, which are the +;; cells that are horizontally, vertically, or diagonally adjacent. + +;; Although this ruleset is superficially simple, it runs very slowly, because +;; all the rules depend on neighbours, which makes them more expensive to +;; compute. + +;; At each step in time, the following transitions occur: + +;; Any live cell with fewer than two live neighbours dies, as if caused by +;; under-population. + +if state is black and fewer than 2 neighbours are black then state should be white + +;; Any live cell with two or three live neighbours lives on to the next generation. + +;; Any live cell with more than three live neighbours dies, as if by overcrowding. + +if state is black and more than 3 neighbours are black then state should be white + +;; Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. + +if state is not black and 3 neighbours are black then state should be black + +# Initialisation rules + +if state is new and altitude is more than 127 then state should be black + +if state is new then state should be white diff --git a/resources/rulesets/ecology.txt b/resources/rulesets/ecology.txt new file mode 100644 index 0000000..e4686f0 --- /dev/null +++ b/resources/rulesets/ecology.txt @@ -0,0 +1,99 @@ +## Ruleset which attempts to model predator/prey ecology (not very well yet) + +## Vegetation rules +;; rules which populate the world with plants + +;; Occasionally, passing birds plant tree seeds into grassland + +if state is grassland then 1 chance in 10 state should be heath + +;; heath below the treeline grows gradually into forest, providing browsing pressure is not to high + +if state is heath and deer are fewer than 6 and altitude is less than 120 then state should be scrub +if state is scrub then 1 chance in 5 state should be forest + +;; Forest on fertile land at low altitude grows to climax + +if state is forest and fertility is more than 5 and altitude is less than 70 then state should be climax + +;; Climax forest occasionally catches fire (e.g. lightning strikes) + +if state is climax then 1 chance in 500 state should be fire + +;; Climax forest neighbouring fires is likely to catch fire +if state is climax and some neighbours are fire then 1 chance in 3 state should be fire + +;; After fire we get waste + +if state is fire then state should be waste + +;; And after waste we get pioneer species; if there's a woodland seed +;; source, it's going to be heath, otherwise grassland. + +if state is waste and some neighbours are scrub then state should be heath +if state is waste and some neighbours are forest then state should be heath +if state is waste and some neighbours are climax then state should be heath +if state is waste then state should be grassland + +## Herbivore rules + +;; rules describing the impact of herbivores on the environment + +;; if there are too many deer for the fertility of the area to sustain, +;; some die or move on. +;; if deer are more than fertility then deer should be fertility / 2 + +;; deer arrive occasionally at the edge of the map. + +if x is 0 or y is 0 and deer are 0 then 1 chance in 50 deer should be 2 + +;; deer gradually spread through the world by breeding or migrating. +if fertility is more than 10 and deer is 0 and some neighbours have deer more than 2 then deer should be 2 + +;; deer breed. + +if deer are more than 1 then deer should be deer * 2 + +## Predator rules + +;; rules describing the impact of predator behaviour on the environment + +if deer are more than wolves then deer should be deer - wolves + +;; if there are not enough deer to sustain the population of wolves, +;; some wolves die or move on. + +if wolves are more than deer then deer should be 0 and wolves should be deer + 0 + +;; wolves arrive occasionally at the edge of the map. + +if x is 0 or y is 0 and wolves are 0 then 1 chance in 50 wolves should be 2 + +;; wolves gradually spread through the world by breeding or migrating. + +if state is not water and wolves is 0 and some neighbours have wolves more than 2 then 1 chance in 5 wolves should be 2 + +;; wolves breed. + +if wolves are more than 1 then wolves should be wolves * 2 + +## Potential blockers + +;; Forest increases soil fertility. +if state is in forest or climax then fertility should be fertility + 1 + + +## Initialisation rules + +;; Rules which deal with state 'new' will waste less time if they're near the +;; end of the file + +;; below the waterline we have water. + +if state is new and altitude is less than 10 then state should be water + +;; above the snowline we have snow. +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 diff --git a/resources/rulesets/harbours.txt b/resources/rulesets/harbours.txt new file mode 100644 index 0000000..2e944a9 --- /dev/null +++ b/resources/rulesets/harbours.txt @@ -0,0 +1,4 @@ +;; 'run once' ruleset to be run after (e.g.) settlement to establish harbours +;; Doesn't work yet, need to find out why and fix it! + +if state is water and more than four neighbours are not water and some neighbours are house then state should be harbour diff --git a/resources/rulesets/iceage.txt b/resources/rulesets/iceage.txt new file mode 100644 index 0000000..4db944e --- /dev/null +++ b/resources/rulesets/iceage.txt @@ -0,0 +1,65 @@ +## Ruleset which attempts to model retreat of ice after an iceage + +;; Limitations: because the rule language doesn't (yet) allow sophisticated +;; arithmetic, the ice retreats north to south (southern hemisphere). Otherwise, +;; it's pretty realistic; ice moves progressively up hillsides, and vegetation +;; gradually re-establishes. + +## Vegetation rules +;; rules which populate the world with plants + +;; Occasionally, passing birds plant tree seeds into grassland + +if state is grassland then 1 chance in 10 state should be heath + +;; heath below the treeline grows gradually into forest, providing browsing pressure is not to high + +if state is heath and fertility is more than 10 and altitude is less than 120 then state should be scrub +if state is scrub and fertility is more than 20 then 1 chance in 20 state should be forest + +;; Forest on fertile land grows to climax + +if state is forest and fertility is more than 30 and altitude is less than 70 then state should be climax + +;; Climax forest occasionally catches fire (e.g. lightning strikes) + +if state is climax then 1 chance in 500 state should be fire + +;; Climax forest neighbouring fires is likely to catch fire +if state is climax and some neighbours are fire then 1 chance in 3 state should be fire + +;; After fire we get waste + +if state is fire then state should be waste + +;; And after waste we get pioneer species; if there's a woodland seed +;; source, it's going to be heath, otherwise grassland. + +if state is waste and some neighbours are scrub then state should be heath +if state is waste and some neighbours are forest then state should be heath +if state is waste and some neighbours are climax then state should be heath +if state is waste then state should be grassland + +## Potential blockers + +;; Woody plants increase soil fertility over time. +if state is in heath or scrub or forest or climax then fertility should be fertility + 1 + + +## Initialisation rules + +;; Rules which deal with state 'new' will waste less time if they're near the +;; end of the file + +if state is new then state should be ice + +;; thaw moves gradually southwards (the distinction between 'ice' and 'snow' is +;; just a hack because I can't do complex arithmetic in rules) +;; below the waterline ice thaws to water. +if state is ice and generation is more than y and altitude is less than 10 then state should be water + +;; otherwise it thaws to snow +if state is ice and generation is more than y then state should be snow + +;; thaw moves gradually up the hills +if state is snow and generation is more than altitude then state should be waste diff --git a/resources/rulesets/settlement.txt b/resources/rulesets/settlement.txt new file mode 100644 index 0000000..f31f7b3 --- /dev/null +++ b/resources/rulesets/settlement.txt @@ -0,0 +1,156 @@ +# Human settlement + +;; This rule set attempts to model human settlement in a landscape. It models +;; western European pre-history moderately well. Settlement first occurs as +;; nomadic camps on coastal promentaries (cells with four or more neighbours +;; that are water). This represents 'kitchen-midden' mesolithic settlement. +;; +;; As grassland becomes available near camps, pastoralists appear, and will +;; follow their herds inland. When pastoralists have available fertile land, +;; they will till the soil and plant crops, and in doing so will establish +;; permanent settlements; this is approximately a neolithic stage. +;; +;; Where soil is fertile, settlements will cluster, and markets will appear. +;; where there is sufficient settlement, the markets become permanent, and you +;; have the appearance of towns. This takes us roughly into the bronze age. +;; +;; This is quite a complex ruleset, and runs quite slowly. However, it does +;; model some significant things. Soil gains in fertility under woodland; deep +;; loams and podzols build up over substantial time. Agriculture depletes +;; fertility. So if forest has become well established before human settlement +;; begins, a higher population (more crops) will eventually be sustainable, +;; whereas if human population starts early the deep fertile soils will not +;; establish and you will have more pastoralism, supporting fewer permanent +;; settlements. + +;; hack to speed up processing on the 'great britain and ireland' map +if state is water then state should be water + +;; nomads make their first significant camp near water because of fish and +;; shellfish (kitchen-midden people) +if state is in grassland or heath and more than 3 neighbours are water and generation is more than 20 then state should be camp + +;; sooner or later nomads learn to keep flocks +if state is in grassland or heath and some neighbours are camp then 1 chance in 2 state should be pasture + +;; and more herds support more people +if state is in grassland or heath and more than 2 neighbours are pasture then 1 chance in 3 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 +if state is in grassland or heath and some neighbours within 2 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 + +;; Impoverished pasture can't be grazed permanently +if state is pasture and fertility is less than 2 then 1 chance in 3 state should be heath + +;; nomads move on +if state is camp then 1 chance in 5 state should be waste + +;; pasture that's too far from a house or camp will be abandoned +if state is pasture and fewer than 1 neighbours within 3 are house and fewer than 1 neighbours within 2 are camp then state should be heath + +;; markets spring up near settlements +if state is in grassland or pasture and more than 1 neighbours are house then 1 chance in 10 state should be market + +;; good fertile pasture close to settlement will be ploughed for crops +if state is pasture and fertility is more than 10 and altitude is less than 100 and some neighbours are camp or some neighbours are house then state should be ploughland + +if state is ploughland then state should be crop + +;; after the crop is harvested, the land is allowed to lie fallow. But cropping +;; depletes fertility. +if state is crop then state should be grassland and fertility should be fertility - 1 + +;; if there's reliable food available, nomads build permanent settlements +if state is in camp or abandoned and some neighbours are crop then state should be house +if state is abandoned and some neighbours are pasture then state should be house +;; people camp near to markets +if state is in waste or grassland and some neighbours are market then state should be camp + +;; a market in a settlement survives +if state is market and some neighbours are inn then state should be market +if state is market then state should be grassland + +;; a house near a market in a settlement will become an inn +if state is house and some neighbours are market and more than 1 neighbours are house then 1 chance in 5 state should be inn +;; but it will need some local custom to survive +if state is inn and fewer than 3 neighbours are house then state should be house + +;; if there aren't enough resources houses should be abandoned +;; resources from fishing +if state is house and more than 2 neighbours are water then state should be house +;; from farming +if state is house and some neighbours are pasture then state should be house +if state is house and some neighbours are ploughland then state should be house +if state is house and some neighbours are crop then state should be house +;; from the market +if state is house and some neighbours are market then state should be house +if state is house then 1 chance in 2 state should be abandoned +if state is abandoned then 1 chance in 5 state should be waste + + +## Vegetation rules +;; rules which populate the world with plants + +;; Occasionally, passing birds plant tree seeds into grassland + +if state is grassland then 1 chance in 10 state should be heath + +;; heath below the treeline grows gradually into forest + +if state is heath and altitude is less than 120 then state should be scrub +if state is scrub then 1 chance in 5 state should be forest + +;; Forest on fertile land grows to climax + +if state is forest and fertility is more than 5 and altitude is less than 70 then state should be climax + +;; Climax forest occasionally catches fire (e.g. lightning strikes) + +if state is climax then 1 chance in 500 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 + +;; After fire we get waste + +if state is fire then state should be waste + +;; waste near settlement that is fertile becomes ploughland +if state is waste and fertility is more than 10 and some neighbours are house or some neighbours are camp then state should be ploughland + +;; And after waste we get pioneer species; if there's a woodland seed +;; source, it's going to be heath, otherwise grassland. + +if state is waste and some neighbours are scrub then state should be heath +if state is waste and some neighbours are forest then state should be heath +if state is waste and some neighbours are climax then state should be heath +if state is waste then state should be grassland + + +## Potential blockers + +;; Forest increases soil fertility. +if state is in forest or climax then fertility should be fertility + 1 + +## Initialisation rules + +;; Rules which deal with state 'new' will waste less time if they're near the +;; end of the file + +;; below the waterline we have water. + +if state is new and altitude is less than 10 then state should be water + +;; above the snowline we have snow. +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 + \ No newline at end of file diff --git a/resources/rulesets/with-drainage.txt b/resources/rulesets/with-drainage.txt new file mode 100644 index 0000000..ea2db55 --- /dev/null +++ b/resources/rulesets/with-drainage.txt @@ -0,0 +1,150 @@ +# Human settlement + +;; This rule set adds ideas aboutv rainfall and river drainage to the human settlement ruleset. +;; This depends on transforming the world with the drainage functions before starting running +;; the rule set, and that isn't done by default because it is computationally expensive. + +;; hack to speed up processing on the 'great britain and ireland' map +if state is sea then state should be sea + +;; nomads make their first significant camp near sea because of fish and +;; shellfish (kitchen-midden people) +if state is in grassland or heath and more than 3 neighbours are sea and generation is more than 20 then state should be camp + +;; sooner or later nomads learn to keep flocks +if state is in grassland or heath and some neighbours are camp then 1 chance in 2 state should be pasture + +;; and more herds support more people +if state is in grassland or heath and more than 2 neighbours are pasture then 1 chance in 3 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 +if state is in grassland or heath and some neighbours within 2 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 + +;; Impoverished pasture can't be grazed permanently +if state is pasture and fertility is less than 2 then 1 chance in 3 state should be heath + +;; nomads move on +if state is camp then 1 chance in 5 state should be waste + +;; pasture that's too far from a house or camp will be abandoned +if state is pasture and fewer than 1 neighbours within 3 are house and fewer than 1 neighbours within 2 are camp then state should be heath + +;; markets spring up near settlements +if state is in grassland or pasture and more than 1 neighbours are house then 1 chance in 10 state should be market + +;; good fertile pasture close to settlement will be ploughed for crops +if state is pasture and fertility is more than 10 and altitude is less than 100 and some neighbours are camp or some neighbours are house then state should be ploughland + +if state is ploughland then state should be crop + +;; after the crop is harvested, the land is allowed to lie fallow. But cropping +;; depletes fertility. +if state is crop then state should be grassland and fertility should be fertility - 1 + +;; if there's reliable food available, nomads build permanent settlements +if state is in camp or abandoned and some neighbours are crop then state should be house +if state is abandoned and some neighbours are pasture then state should be house +;; people camp near to markets +if state is in waste or grassland and some neighbours are market then state should be camp + +;; a market in a settlement survives +if state is market and some neighbours are inn then state should be market +;; a market at a river mouth survives +if state is market and some neighbours are navigable and some neighbours are sea then state should be market +;; otherwise markets are transitory +if state is market then state should be grassland + +;; a house near a market in a settlement will become an inn +if state is house and some neighbours are market and more than 1 neighbours are house then 1 chance in 5 state should be inn +;; but it will need some local custom to survive +if state is inn and fewer than 3 neighbours are house then state should be house + +;; if there aren't enough resources houses should be abandoned +;; resources from fishing +if state is house and more than 2 neighbours are sea then state should be house +;; from farming +if state is house and some neighbours are pasture then state should be house +if state is house and some neighbours are ploughland then state should be house +if state is house and some neighbours are crop then state should be house +;; from the market +if state is house and some neighbours are market then state should be house +if state is house then 1 chance in 2 state should be abandoned +if state is abandoned then 1 chance in 5 state should be waste + + +## Vegetation rules +;; rules which populate the world with plants + +;; Occasionally, passing birds plant tree seeds into grassland + +if state is grassland then 1 chance in 10 state should be heath + +;; heath below the treeline grows gradually into forest + +if state is heath and altitude is less than 120 then state should be scrub +if state is scrub then 1 chance in 5 state should be forest + +;; Forest on fertile land grows to climax + +if state is forest and fertility is more than 5 and altitude is less than 70 then state should be climax + +;; Climax forest occasionally catches fire (e.g. lightning strikes) + +if state is climax then 1 chance in 500 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 climax and more than 3 neighbours within 2 are house then state should be scrub + +;; After fire we get waste + +if state is fire then state should be waste + +;; waste near settlement that is fertile becomes ploughland +if state is waste and fertility is more than 10 and some neighbours are house or some neighbours are camp then state should be ploughland + +;; And after waste we get pioneer species; if there's a woodland seed +;; source, it's going to be heath, otherwise grassland. + +if state is waste and some neighbours are scrub then state should be heath +if state is waste and some neighbours are forest then state should be heath +if state is waste and some neighbours are climax then state should be heath +if state is waste then state should be grassland + + +## Rivers connected to the sea are navigable +if state is river and some neighbours are sea then state should be navigable +if state is river and some neighbours are navigable then state should be navigable + +## Where navigable water meets the sea, ports are probable +if state is in grassland or heath or scrub and some neighbours are sea and some neighbours are navigable and some neighbours are house then state should be market + +## Potential blockers + +;; Forest increases soil fertility. +if state is in forest or climax then fertility should be fertility + 1 + +## Initialisation rules + +;; Rules which deal with state 'new' will waste less time if they're near the +;; end of the file + +;; below the high-tide line we have sea. + +if state is new and altitude is less than 10 then state should be sea + +;; above the high-tide line, there's a threshold of water pressure above which we have rivers +;; the actual threshold will need tuning, 30 is a guess. +if state is new and flow is more than 30 then state should be river + +;; above the snowline we have snow. +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 diff --git a/resources/tiles/life/black.png b/resources/tiles/life/black.png new file mode 100644 index 0000000..9e48aa6 Binary files /dev/null and b/resources/tiles/life/black.png differ diff --git a/resources/tiles/life/red.png b/resources/tiles/life/red.png new file mode 100644 index 0000000..f4409bc Binary files /dev/null and b/resources/tiles/life/red.png differ diff --git a/resources/tiles/life/white.png b/resources/tiles/life/white.png new file mode 100644 index 0000000..0012011 Binary files /dev/null and b/resources/tiles/life/white.png differ diff --git a/resources/tiles/world/abandoned.png b/resources/tiles/world/abandoned.png new file mode 100644 index 0000000..1492e7e Binary files /dev/null and b/resources/tiles/world/abandoned.png differ diff --git a/resources/tiles/world/camp.png b/resources/tiles/world/camp.png new file mode 100644 index 0000000..c2ecf86 Binary files /dev/null and b/resources/tiles/world/camp.png differ diff --git a/resources/tiles/world/climax.png b/resources/tiles/world/climax.png new file mode 100644 index 0000000..03f0273 Binary files /dev/null and b/resources/tiles/world/climax.png differ diff --git a/resources/tiles/world/crop.png b/resources/tiles/world/crop.png new file mode 100644 index 0000000..b154cdc Binary files /dev/null and b/resources/tiles/world/crop.png differ diff --git a/resources/tiles/world/error.png b/resources/tiles/world/error.png new file mode 100644 index 0000000..f4409bc Binary files /dev/null and b/resources/tiles/world/error.png differ diff --git a/resources/tiles/world/fire.png b/resources/tiles/world/fire.png new file mode 100644 index 0000000..e4537be Binary files /dev/null and b/resources/tiles/world/fire.png differ diff --git a/resources/tiles/world/forest.png b/resources/tiles/world/forest.png new file mode 100644 index 0000000..0d159c4 Binary files /dev/null and b/resources/tiles/world/forest.png differ diff --git a/resources/tiles/world/grassland.png b/resources/tiles/world/grassland.png new file mode 100644 index 0000000..85296c9 Binary files /dev/null and b/resources/tiles/world/grassland.png differ diff --git a/resources/tiles/world/harbour.png b/resources/tiles/world/harbour.png new file mode 100644 index 0000000..2fe5133 Binary files /dev/null and b/resources/tiles/world/harbour.png differ diff --git a/resources/tiles/world/heath.png b/resources/tiles/world/heath.png new file mode 100644 index 0000000..eba54f5 Binary files /dev/null and b/resources/tiles/world/heath.png differ diff --git a/resources/tiles/world/house.png b/resources/tiles/world/house.png new file mode 100644 index 0000000..222e81a Binary files /dev/null and b/resources/tiles/world/house.png differ diff --git a/resources/tiles/world/ice.png b/resources/tiles/world/ice.png new file mode 100644 index 0000000..1349ef0 Binary files /dev/null and b/resources/tiles/world/ice.png differ diff --git a/resources/tiles/world/inn.png b/resources/tiles/world/inn.png new file mode 100644 index 0000000..67cbf58 Binary files /dev/null and b/resources/tiles/world/inn.png differ diff --git a/resources/tiles/world/market.png b/resources/tiles/world/market.png new file mode 100644 index 0000000..a4f3bdb Binary files /dev/null and b/resources/tiles/world/market.png differ diff --git a/resources/tiles/world/meadow.png b/resources/tiles/world/meadow.png new file mode 100644 index 0000000..44453f9 Binary files /dev/null and b/resources/tiles/world/meadow.png differ diff --git a/resources/tiles/world/navigable.png b/resources/tiles/world/navigable.png new file mode 100644 index 0000000..f4409bc Binary files /dev/null and b/resources/tiles/world/navigable.png differ diff --git a/resources/tiles/world/pasture.png b/resources/tiles/world/pasture.png new file mode 100644 index 0000000..44453f9 Binary files /dev/null and b/resources/tiles/world/pasture.png differ diff --git a/resources/tiles/world/plague.png b/resources/tiles/world/plague.png new file mode 100644 index 0000000..4235d08 Binary files /dev/null and b/resources/tiles/world/plague.png differ diff --git a/resources/tiles/world/ploughland.png b/resources/tiles/world/ploughland.png new file mode 100644 index 0000000..0df26f8 Binary files /dev/null and b/resources/tiles/world/ploughland.png differ diff --git a/resources/tiles/world/river.png b/resources/tiles/world/river.png new file mode 100644 index 0000000..008b705 Binary files /dev/null and b/resources/tiles/world/river.png differ diff --git a/resources/tiles/world/scrub.png b/resources/tiles/world/scrub.png new file mode 100644 index 0000000..f4dd581 Binary files /dev/null and b/resources/tiles/world/scrub.png differ diff --git a/resources/tiles/world/sea.png b/resources/tiles/world/sea.png new file mode 100644 index 0000000..008b705 Binary files /dev/null and b/resources/tiles/world/sea.png differ diff --git a/resources/tiles/world/snow.png b/resources/tiles/world/snow.png new file mode 100644 index 0000000..1349ef0 Binary files /dev/null and b/resources/tiles/world/snow.png differ diff --git a/resources/tiles/world/waste.png b/resources/tiles/world/waste.png new file mode 100644 index 0000000..0f6b6a4 Binary files /dev/null and b/resources/tiles/world/waste.png differ diff --git a/resources/tiles/world/water.png b/resources/tiles/world/water.png new file mode 100644 index 0000000..008b705 Binary files /dev/null and b/resources/tiles/world/water.png differ diff --git a/src/mw_desktop/core.clj b/src/mw_desktop/core.clj new file mode 100644 index 0000000..5dea61b --- /dev/null +++ b/src/mw_desktop/core.clj @@ -0,0 +1,31 @@ +(ns mw-desktop.core + (:require [clojure.java.io :refer [file]] + [clojure.tools.cli :refer [parse-opts]]) + (:gen-class)) + +(def cli-options + [["-f FILEPATH" "--file-path FILEPATH" + "Set the path to the directory for reading and writing Lisp files." + :validate [#(and (.exists (file %)) + (.isDirectory (file %)) + (.canRead (file %)) + (.canWrite (file %))) + "File path must exist and must be a directory."]] + ["-h" "--help"] + ["-p PROMPT" "--prompt PROMPT" "Set the REPL prompt to PROMPT" + :default "Sprecan::"] + ["-r SYSOUTFILE" "--read SYSOUTFILE" "Read Lisp system from file SYSOUTFILE" + :validate [#(and + (.exists (file %)) + (.canRead (file %))) + "Could not find sysout file"]] + ["-s" "--strict" "Strictly interpret the Lisp 1.5 language, without extensions."] + ["-t" "--time" "Time evaluations."] + ["-x" "--testing" "Disable the jline reader - useful when piping input."]]) + +(defn -main + "Parse options, print the banner, read the init file if any, and enter the + read/eval/print loop." +[& opts] +(let [args (parse-opts opts cli-options)] + (println "Hello, World!"))) diff --git a/src/mw_desktop/e12_interactive_development.clj b/src/mw_desktop/e12_interactive_development.clj new file mode 100644 index 0000000..a64a55c --- /dev/null +++ b/src/mw_desktop/e12_interactive_development.clj @@ -0,0 +1,252 @@ + +;; this file is cribbed entirely from +;; https://github.com/cljfx/cljfx/blob/master/examples/e12_interactive_development.clj + +;; This file is supposed to be explored from the REPL, evaluating forms one +;; by one from top to bottom. + +(ns e12-interactive-development + (:require [cljfx.api :as fx])) + +;; I want to build an interactive chart that shows how bouncing object falls +;; on the ground. I want to be able to edit gravity and friction to see how +;; it affects object's behavior, so I will put it into state: + +(def *state + (atom {:gravity 10 + :friction 0.4})) + + +;; I want to have map event handlers extensible during runtime to avoid full app +;; restarts. One way is using vars instead of functions to get that kind of +;; behavior, but I'll go with another way: multi-methods. + +(defmulti event-handler :event/type) + +;; Now we'll create our app with dummy root view + +(defn root-view [{{:keys [gravity friction]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :h-box + :children [{:fx/type :label + :text (str "g = " gravity ", f = " friction)}]}}}) + +(def renderer + (fx/create-renderer + :middleware (fx/wrap-map-desc (fn [state] + {:fx/type root-view + :state state})) + :opts {:fx.opt/map-event-handler event-handler})) + +(fx/mount-renderer *state renderer) + +;; At this point, really tiny window appears that displays current gravity and +;; friction. We want to have an ability to change these values, so let's create +;; some slider views for them: + +(defn slider-view [{:keys [min max value]}] + {:fx/type :slider + :min min + :max max + :value value}) + +;; Now we will update our root view to display these sliders: + +(defn root-view [{{:keys [gravity friction]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :h-box + :children [{:fx/type slider-view + :min 0 + :max 100 + :value gravity} + {:fx/type slider-view + :min 0 + :max 1 + :value friction}]}}}) + +;; Now we updated our root function, but window didn't change. It happens +;; because cljfx has no way to know if definition of some component functions is +;; changed. But we can ask renderer to refresh itself by calling it without any +;; arguments: + +(renderer) +;; Now small label got replaced with 2 sliders. Problem is, there are no labels +;; on them, so users can't really see what these sliders mean, so let's fix it: + +(defn slider-view [{:keys [min max value label]}] + {:fx/type :v-box + :children [{:fx/type :label + :text label} + {:fx/type :slider + :min min + :max max + :value value + :major-tick-unit max + :show-tick-labels true}]}) + +(defn root-view [{{:keys [gravity friction]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :h-box + :spacing 10 + :children [{:fx/type slider-view + :min 0 + :max 100 + :value gravity + :label "Gravity"} + {:fx/type slider-view + :min 0 + :max 1 + :label "Friction" + :value friction}]}}}) + +(renderer) + + +;; Great, time to add a chart that uses gravity and friction, but first let's +;; try to display something dummy to make sure it works + +(defn chart-view [{:keys [gravity friction]}] + {:fx/type :line-chart + :x-axis {:fx/type :number-axis + :label "Time"} + :y-axis {:fx/type :number-axis + :label "Y"} + :data [{:fx/type :xy-chart-series + :name "Position by time" + :data (for [t (range 100)] + {:fx/type :xy-chart-data + :x-value t + :y-value t})}]}) + +(defn root-view [{{:keys [gravity friction]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :v-box + :spacing 20 + :children [{:fx/type chart-view + :gravity gravity + :friction friction} + {:fx/type :h-box + :spacing 10 + :alignment :center + :children [{:fx/type slider-view + :min 0 + :max 100 + :value gravity + :label "Gravity"} + {:fx/type slider-view + :min 0 + :max 1 + :label "Friction" + :value friction}]}]}}}) + +(renderer) + +;; Now chart is added to a window. Everything looks fine, time to do some +;; simulation: + +(defn simulate-step [{:keys [velocity y]} gravity friction] + (let [new-velocity (* (- velocity gravity) (- 1 friction)) + new-y (+ y new-velocity)] + (if (neg? new-y) + {:velocity (- new-velocity) :y 0} + {:velocity new-velocity :y new-y}))) + +(defn chart-view [{:keys [gravity friction]}] + {:fx/type :line-chart + :x-axis {:fx/type :number-axis + :label "Time"} + :y-axis {:fx/type :number-axis + :label "Y"} + :data [{:fx/type :xy-chart-series + :name "Position by time" + :data (->> {:velocity 0 :y 100} + (iterate #(simulate-step % gravity friction)) + (take 100) + (map-indexed (fn [index {:keys [y]}] + {:fx/type :xy-chart-data + :x-value index + :y-value y})))}]}) + +(renderer) + +(defmethod event-handler ::set-friction [e] + (swap! *state assoc :friction (:fx/event e))) + +(defmethod event-handler ::set-gravity [e] + (swap! *state assoc :gravity (:fx/event e))) + +(defn slider-view [{:keys [min max value label event]}] ;; add event as arg + {:fx/type :v-box + :children [{:fx/type :label + :text label} + {:fx/type :slider + :min min + :max max + :value value + :on-value-changed {:event/type event} ;; fire it on value + :major-tick-unit max + :show-tick-labels true}]}) + +(defn root-view [{{:keys [gravity friction]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :v-box + :spacing 20 + :children [{:fx/type chart-view + :gravity gravity + :friction friction} + {:fx/type :h-box + :spacing 10 + :alignment :center + :children [{:fx/type slider-view + :min 0 + :max 100 + :value gravity + :label "Gravity" + :event ::set-gravity} ;; provide events + {:fx/type slider-view + :min 0 + :max 1 + :label "Friction" + :value friction + :event ::set-friction}]}]}}}) + +(renderer) + +(swap! *state assoc :gravity 1) + +(defn root-view [{{:keys [gravity friction]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :v-box + :spacing 20 + :children [{:fx/type chart-view + :gravity gravity + :friction friction} + {:fx/type :h-box + :spacing 10 + :alignment :center + :children [{:fx/type slider-view + :min 0 + :max 5 ;; 100 -> 5 + :value gravity + :label "Gravity" + :event ::set-gravity} + {:fx/type slider-view + :min 0 + :max 1 + :label "Friction" + :value friction + :event ::set-friction}]}]}}}) + +(renderer) \ No newline at end of file diff --git a/src/mw_desktop/e20_markdown_editor.clj b/src/mw_desktop/e20_markdown_editor.clj new file mode 100644 index 0000000..4151cbd --- /dev/null +++ b/src/mw_desktop/e20_markdown_editor.clj @@ -0,0 +1,272 @@ +;; lightly adapted from +;; https://github.com/cljfx/cljfx/blob/master/examples/e20_markdown_editor.clj +(ns mw-desktop.e20-markdown-editor + (:require [cljfx.api :as fx] + [clojure.core.cache :refer [lru-cache-factory]] + [clojure.java.io :refer [resource]] + [clojure.string :refer [join lower-case starts-with?]]) + (:import [java.awt Desktop] + [java.io File] + [java.net URI] + [org.commonmark.node Node] + [org.commonmark.parser Parser])) + +;; does not work any more :( +#_(SvgImageLoaderFactory/install (PrimitiveDimensionProvider.)) + +(def *context + (atom + (fx/create-context {:typed-text (slurp (resource "doc/grammar.md"))} + #(lru-cache-factory % :threshold 4096)))) + +(defn commonmark->clj [^Node node] + (let [tag (->> node + .getClass + .getSimpleName + (re-seq #"[A-Z][a-z]+") + (map lower-case) + (join "-") + keyword) + all-attrs (->> node + bean + (map (fn [[k v]] + [(->> k + name + (re-seq #"[A-Z]?[a-z]+") + (map lower-case) + (join "-") + keyword) + v])) + (into {}))] + {:tag tag + :attrs (dissoc all-attrs :next :previous :class :first-child :last-child :parent) + :children (->> node + .getFirstChild + (iterate #(.getNext ^Node %)) + (take-while some?) + (mapv commonmark->clj))})) + +(defn node-sub [context] + (-> (Parser/builder) + .build + (.parse (fx/sub-val context :typed-text)) + commonmark->clj)) + +(defmulti handle-event :event/type) + +(defmethod handle-event :default [e] + (prn e)) + +(defmethod handle-event ::type-text [{:keys [fx/event fx/context]}] + {:context (fx/swap-context context assoc :typed-text event)}) + +(defmulti md->fx :tag) + +(defn md-view [{:keys [node]}] + (md->fx node)) + +(defmethod md->fx :heading [{children :children {:keys [level]} :attrs}] + {:fx/type :text-flow + :style-class ["heading" (str "level-" level)] + :children (for [node children] + {:fx/type md-view + :node node})}) + +(defmethod md->fx :paragraph [{children :children}] + {:fx/type :text-flow + :style-class "paragraph" + :children (for [node children] + {:fx/type md-view + :node node})}) + +(defmethod md->fx :text [{{:keys [literal]} :attrs}] + {:fx/type :text + :cache true + :cache-hint :speed + :text literal}) + +(defmethod md->fx :code [{{:keys [literal]} :attrs}] + {:fx/type :label + :cache true + :cache-hint :speed + :style-class "code" + :text literal}) + +(defmethod md->fx :fenced-code-block [{{:keys [literal]} :attrs}] + {:fx/type :v-box + :padding {:top 9} + :children [{:fx/type :scroll-pane + :style-class ["scroll-pane" "code-block"] + :fit-to-width true + :content {:fx/type :label + :cache true + :cache-hint :speed + :max-width ##Inf + :min-width :use-pref-size + :text literal}}]}) + +(defmethod md->fx :indented-code-block [{{:keys [literal]} :attrs}] + {:fx/type :v-box + :padding {:top 9} + :children [{:fx/type :scroll-pane + :style-class ["scroll-pane" "code-block"] + :fit-to-width true + :content {:fx/type :label + :cache true + :cache-hint :speed + :max-width ##Inf + :min-width :use-pref-size + :text literal}}]}) + +(defmethod md->fx :link [{{:keys [^String destination]} :attrs children :children}] + (let [link {:fx/type :hyperlink + :on-action (fn [_] + (future + (try + (if (starts-with? destination "http") + (.browse (Desktop/getDesktop) (URI. destination)) + (.open (Desktop/getDesktop) (File. destination))) + (catch Exception e + (.printStackTrace e)))))}] + (if (and (= 1 (count children)) + (= :text (:tag (first children)))) + (assoc link :text (-> children first :attrs :literal)) + (assoc link :graphic {:fx/type :h-box + :children (for [node children] + {:fx/type md-view + :node node})})))) + +(defmethod md->fx :strong-emphasis [{:keys [children]}] + (if (and (= 1 (count children)) + (= :text (:tag (first children)))) + {:fx/type :text + :cache true + :cache-hint :speed + :style-class "strong-emphasis" + :text (-> children first :attrs :literal)} + {:fx/type :h-box + :cache true + :style-class "strong-emphasis" + :children (for [node children] + {:fx/type md-view + :node node})})) + +(defmethod md->fx :emphasis [{:keys [children]}] + (if (and (= 1 (count children)) + (= :text (:tag (first children)))) + {:fx/type :text + :cache true + :cache-hint :speed + :style-class "emphasis" + :text (-> children first :attrs :literal)} + {:fx/type :h-box + :style-class "emphasis" + :children (for [node children] + {:fx/type md-view + :node node})})) + +(defmethod md->fx :soft-line-break [_] + {:fx/type :text + :text " "}) + +(defmethod md->fx :document [{:keys [children]}] + {:fx/type :v-box + :style-class "document" + :children (for [node children] + {:fx/type md-view + :node node})}) + +(defmethod md->fx :image [{{:keys [destination]} :attrs}] + {:fx/type :image-view + :image {:url (if (starts-with? destination "http") + destination + (str "file:" destination)) + :background-loading true}}) + +(defmethod md->fx :bullet-list [{{:keys [bullet-marker]} :attrs children :children}] + {:fx/type :v-box + :style-class "md-list" + :children (for [node children] + {:fx/type :h-box + :alignment :baseline-left + :spacing 4 + :children [{:fx/type :label + :min-width :use-pref-size + :cache true + :cache-hint :speed + :text (str bullet-marker)} + {:fx/type md-view + :node node}]})}) + +(defmethod md->fx :ordered-list [{{:keys [delimiter start-number]} :attrs + children :children}] + {:fx/type :v-box + :style-class "md-list" + :children (map (fn [child number] + {:fx/type :h-box + :alignment :baseline-left + :spacing 4 + :children [{:fx/type :label + :cache true + :cache-hint :speed + :min-width :use-pref-size + :text (str number delimiter)} + (assoc (md->fx child) + :h-box/hgrow :always)]}) + children + (range start-number ##Inf))}) + +(defmethod md->fx :list-item [{:keys [children]}] + {:fx/type :v-box + :children (for [node children] + {:fx/type md-view + :node node})}) + +(defmethod md->fx :default [{:keys [tag attrs children]}] + {:fx/type :v-box + :children [{:fx/type :label + :cache true + :cache-hint :speed + :style {:-fx-background-color :red} + :text (str tag " " attrs)} + {:fx/type :v-box + :padding {:left 10} + :children (for [node children] + {:fx/type md-view + :node node})}]}) + +(defn note-input [{:keys [fx/context]}] + {:fx/type :text-area + :style-class "input" + :text (fx/sub-val context :typed-text) + :on-text-changed {:event/type ::type-text :fx/sync true}}) + +(defn note-preview [{:keys [fx/context]}] + {:fx/type :scroll-pane + :fit-to-width true + :content {:fx/type md-view + :node (fx/sub-ctx context node-sub)}}) + +(def app + (fx/create-app *context + :event-handler handle-event + :desc-fn (fn [_] + {:fx/type :stage + :showing true + :width 960 + :height 540 + :scene {:fx/type :scene + :stylesheets #{"doc/markdown.css"} + :root {:fx/type :grid-pane + :padding 10 + :hgap 10 + :column-constraints [{:fx/type :column-constraints + :percent-width 100/2} + {:fx/type :column-constraints + :percent-width 100/2}] + :row-constraints [{:fx/type :row-constraints + :percent-height 100}] + :children [{:fx/type note-input + :grid-pane/column 0} + {:fx/type note-preview + :grid-pane/column 1}]}}}))) diff --git a/src/mw_desktop/fxui.clj b/src/mw_desktop/fxui.clj new file mode 100644 index 0000000..52f28a7 --- /dev/null +++ b/src/mw_desktop/fxui.clj @@ -0,0 +1,109 @@ +(ns mw-desktop.fxui + (:require [cljfx.api :as fx] + [clojure.core.cache :refer [lru-cache-factory]] + [clojure.java.io :refer [resource]] + [clojure.string :refer [join lower-case starts-with?]] + [mw-desktop.state :refer [get-state state update-state!]]) + (:import [java.awt Desktop] + [java.io File] + [java.net URI] + [org.commonmark.node Node] + [org.commonmark.parser Parser])) + +;; OK, the basic idea here is we have a window divided vertically +;; into two panes. The user can drag the division between the panes +;; left and right. In the left pane is always the world; in the right, a +;; number of pages can be displayed. +;; +;; 1. Documentation; +;; 2. The rule editor; +;; 3. The log; +;; 4. Data on what states are in use (and how many of each); +;; 5. Some way to get data on other properties (for the mutual aid model, we +;; want to see how much food in total there is in the world, how much the +;; richest centile has, how much the poorest, and how that's changing over +;; time; but whether I have the skill to make that something the user can +;; configure is another matter). +;; +;; There is a File menu with options to: +;; +;; 1. Save the world as an EDN file; +;; 2. Load the world from an EDN file; +;; 3. Create a world from a height map; +;; 4. Load a rules file; +;; 5. Save a rules file; +;; 4. Load (? or register?) a tile set (probably as a jar file?); +;; +;; There is a World menu with options to: +;; +;; 1. Start the world running; +;; 2. Pause/Stop the run; +;; 3. Select a tile set; +;; +;; There is a View menu with options to change the display in the right +;; hand pane. +;; +;; 1. The rule editor; +;; 2. The documentation; +;; 3. Stats displays (but this needs more thought and experimentation) +;; +;; One thought is I might define new rule language to create graphs and charts. +;; +;; 'timeseries total food where state is house group by decile' +;; 'timeseries total food where state is house, fertility where state is pasture or crop or fallow' +;; 'graph fertility by altitude' +;; 'barchart fertility by state' +;; 'piechart count group by state' +;; +;; In which case you probably have one graph page per rule. +(defn- tile-image [{:keys [url]}] + {:fx/type :image-view + :image {:url url + :requested-width 20 + :preserve-ratio true + :background-loading true}}) + +(defn world-view [{:keys [world tileset]}] + ;; assumes that by the time we get here, a tileset is a clojure map + ;; in which the keys are the names of the tiles, without file extension, as + ;; keywords (i.e. they're states, from the point of view of the world), and + ;; in which the values are just java images (bitmaps), or else maps which + ;; wrap java images with some other related data for example dimensions. + (let [th (or (:height (first tileset)) 20) + tw (or (:width (first tileset)) 20) + cols (count (first world)) + rows (count world)] + {:fx/type :tile-pane + :hgap 0 + :pref-columns cols + :pref-rows rows + :pref-tile-height th + :pref-tile-width tw + :vgap 0 + :children (map (fn [cell]{:fx/type tile-image + :tile-pane/alignment :bottom-center + :url (resource (format "%s/%s.png" tileset (:state cell)))}) + (flatten world)) + })) + +(defn root-view [{{:keys [world rules]} :state}] + {:fx/type :stage + :showing true + :scene {:fx/type :scene + :root {:fx/type :split-pane + :items [{:fx.type :scroll-pane + :content {:fx/type world-view}}]}}}) + +(defmulti event-handler + "Multi-method event handler cribbed from e12-interactive-development" + :event/type) + +(def renderer + "Renderer cribbed from e12-interactive-development" + (fx/create-renderer + :middleware (fx/wrap-map-desc (fn [state] + {:fx/type root-view + :state state})) + :opts {:fx.opt/map-event-handler event-handler})) + +(fx/mount-renderer state renderer) \ No newline at end of file diff --git a/src/mw_desktop/state.clj b/src/mw_desktop/state.clj new file mode 100644 index 0000000..4d715de --- /dev/null +++ b/src/mw_desktop/state.clj @@ -0,0 +1,48 @@ +(ns mw-desktop.state + "Global state of the application." + (:require [mw-engine.utils :refer [member?]] + [mw-engine.world :refer [world?]]) + (:import [clojure.lang Keyword])) + +(def valid-states + #{:init :halted :halt-requested :running}) + +(def state + "Global state of the application." + (atom {:state :init})) + +(defn get-state [^Keyword key] + (@state key)) + +(defn await-state + "Pause the current process until the global status is in the state `state-value`." + [state-value] + (while (not= (@state :state) state-value) + (Thread/sleep 10000))) + +(defn update-state! + "Update the global state of the application. The arguments should + be key-value pairs." + [& kvs] + (when-not (and (even? (count kvs)) + (every? keyword? (take-nth 2 kvs))) + (throw (IllegalArgumentException. + "update-state expects an even number of arguments, and that every odd-numbered argument should be a keyword"))) + (let [deltas (into {} (map #(apply vector %) (partition 2 kvs)))] + ;; there's probably a list of checks to be made here, and we probably + ;; want it to be able to add checks at runtime (?) + (when (and (:world deltas) (not (world? (:world deltas)))) + (throw (ex-info "Attempt to set an invalid world" + {:deltas deltas + :state @state}))) + ;; you can't change either the world or the rules while the engine is computing + ;; a new status for the world. + (when-not (= (@state :state) :init) + (when (or (member? (keys deltas) :world) + (member? (keys deltas) :rules)) + (await-state :halted)) ) + (swap! state merge deltas) + (when (and (= (@state :state) :init) + (:world state) + (:rules state)) + (swap! state merge {:state :halted})))) \ No newline at end of file diff --git a/src/mw_desktop/swing_ui.clj b/src/mw_desktop/swing_ui.clj new file mode 100644 index 0000000..26ae223 --- /dev/null +++ b/src/mw_desktop/swing_ui.clj @@ -0,0 +1,154 @@ +(ns mw-desktop.swing-ui + (:require [clojure.java.io :refer [resource]] + [clojure.string :refer [join]] + [markdown.core :refer [md-to-html-string]] + [mw-desktop.state :refer [get-state update-state!]] + [seesaw.core :refer [border-panel editor-pane frame + left-right-split menu menu-item menubar native! pack! + scrollable separator show! tabbed-panel table text]]) + (:import [org.htmlcleaner CleanerProperties HtmlCleaner SimpleHtmlSerializer])) + +;; OK, the basic idea here is we have a window divided vertically +;; into two panes. The user can drag the division between the panes +;; left and right. In the left pane is always the world; in the right, a +;; number of pages can be displayed. +;; +;; 1. Documentation; +;; 2. The rule editor; +;; 3. The log; +;; 4. Data on what states are in use (and how many of each); +;; 5. Some way to get data on other properties (for the mutual aid model, we +;; want to see how much food in total there is in the world, how much the +;; richest centile has, how much the poorest, and how that's changing over +;; time; but whether I have the skill to make that something the user can +;; configure is another matter). +;; +;; There is a File menu with options to: +;; +;; 1. Save the world as an EDN file; +;; 2. Load the world from an EDN file; +;; 3. Create a world from a height map; +;; 4. Load a rules file; +;; 5. Save a rules file; +;; 4. Load (? or register?) a tile set (probably as a jar file?); +;; +;; There is a World menu with options to: +;; +;; 1. Start the world running; +;; 2. Pause/Stop the run; +;; 3. Select a tile set; +;; +;; There is a View menu with options to change the display in the right +;; hand pane. +;; +;; 1. The rule editor; +;; 2. The documentation; +;; 3. Stats displays (but this needs more thought and experimentation) +;; +;; One thought is I might define new rule language to create graphs and charts. +;; +;; 'timeseries total food where state is house group by decile' +;; 'timeseries total food where state is house, fertility where state is pasture or crop or fallow' +;; 'graph fertility by altitude' +;; 'barchart fertility by state' +;; 'piechart count group by state' +;; +;; In which case you probably have one graph page per rule. + +(update-state! :world-view (table :model [:columns [{:key :name, :text "Name"} :likes] + :rows '[["Bobby" "Laura Palmer"] + ["Agent Cooper" "Cherry Pie"] + {:likes "Laura Palmer" :name "James"} + {:name "Big Ed" :likes "Norma Jennings"}]]) + :rule-editor (text :editable? true + :id :rule-editor + :multi-line? true + :text ";; This is where you will write your rules.") + :error-panel (text :editable? false + :id :error-panel + :foreground "maroon" + :multi-line? true + :text ";; Errors will be shown here.")) + +(defn markdown->html + "`md-to-html-string` returns an HTML fragment that `editor-pane` chokes on. + This is an attempt to do better. It sort-of works -- produces nice clean + HTML -- but the performance of `editor-pane` is still unacceptably poor" + [md-text] + (let [props (CleanerProperties.)] + (.setOmitDoctypeDeclaration props false) + (.setOmitDeprecatedTags props true) + (.setOmitUnknownTags props true) + (.setOmitXmlDeclaration props true) + (.getAsString (SimpleHtmlSerializer. props) + (.clean (HtmlCleaner. props) (md-to-html-string md-text))))) + +(defn make-multi-view + "Make the right hand multi-view panel." + [] + (tabbed-panel + :tabs [{:title "Rules" + :content (border-panel + :center (scrollable + (border-panel + :center (get-state :rule-editor) + :west (text :columns 4 + :editable? false + :foreground "cornflowerblue" + :id :line-numbers + :multi-line? true + :text (join "\n" + (map str (range 1 1000))) + :wrap-lines? false))) + :south (scrollable + (get-state :error-panel)))} + {:title "Grammar" + :content (scrollable + ;; the performance of laying out HTML in an editor-pane + ;; is painful! RTF is better but not good, and unreliable. + (editor-pane :editable? false + ;; :multi-line? true + :content-type "text/plain" + :text (slurp + (resource "doc/grammar.md")) + ;; :wrap-lines? true + ))}])) + +(update-state! :multi-view (make-multi-view)) + +(defn create-app-window + "Create the app window." + [] + (native!) + (update-state! :app-window + (pack! + (frame :title "MicroWorld" + ;; :size [600 :by 600] + ;; :on-close :exit + :menubar (menubar + :items + [(menu :text "World" :items + [(menu-item :text "Run World" :enabled? false) + (menu-item :text "Halt Run" :enabled? false) + (separator) + (menu :text "Create World..." :items + [(menu-item :text "From Heightmap...") + (menu-item :text "From Coordinates...")]) + (menu-item :text "Load World File...") + (menu-item :text "Save World File As...") + (separator) + (menu-item :text "Import Tile Set...")]) + (menu :text "Rules" :items + [(menu-item :text "New Rule Set") + (menu-item :text "Open Rule Set...") + (menu-item :text "Save Rule Set") + (menu-item :text "Save Rule Set As...") + (separator) + (menu-item :text "Compile Rules")]) + (menu :text "Help" :items + [(menu-item :text "About MicroWorld")])]) + :content (left-right-split (scrollable (get-state :world-view)) + (scrollable (get-state :multi-view)) + :divider-location 8/10))))) + +(defn show-app-window [] (show! (get-state :app-window))) diff --git a/test/mw_desktop/core_test.clj b/test/mw_desktop/core_test.clj new file mode 100644 index 0000000..d39ee36 --- /dev/null +++ b/test/mw_desktop/core_test.clj @@ -0,0 +1,7 @@ +(ns mw-desktop.core-test + (:require [clojure.test :refer :all] + [mw-desktop.core :refer :all])) + +(deftest a-test + (testing "FIXME, I fail." + (is (= 0 1))))