Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active June 30, 2018 01:12
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save kenwebb/41dceb5cd5c809a49729bcc78ef332b7 to your computer and use it in GitHub Desktop.
Island 3
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Fri Jun 29 2018 21:12:05 GMT-0400 (Eastern Daylight Time)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: Island 3
Description:
Url: http://www.primordion.com/Xholon/gwt/
InternalName: 41dceb5cd5c809a49729bcc78ef332b7 based on 4afa0d063848c2c040cf7d109a180a88 based on c8e4d796b9d76021d677a1d712ecadae
Keywords:
My Notes
--------
May 23, 2018
Jen and I met yesterday to kick off the Island project. See my written notes from yesterday.
She described her initial requirements, and I will implement an initial prototype in this Xholon workbook.
To Run
------
http://www.primordion.com/Xholon/gwt/Xholon.html?app=c8e4d796b9d76021d677a1d712ecadae&src=gist&gui=none
http://127.0.0.1:8888/Xholon.html?app=Island+1&src=lstr&gui=none
http://localhost:3000/?app=4afa0d063848c2c040cf7d109a180a88&src=gist&gui=none
http://localhost:3000/?app=41dceb5cd5c809a49729bcc78ef332b7&src=gist&gui=none
https://xholon3.meteorapp.com/?app=41dceb5cd5c809a49729bcc78ef332b7&src=gist&gui=none
Backstory
---------
A castaway tries to survive on a small island with renewable but limited resources.
Castaway
--------
For now, I will use the Xholon system Avatar as the single "castaway" on the island.
TODO the castaway will have a Calorie meter and a Health meter
Fish
----
A fish is an individual node containing zero or more behaviors, similar to a cat in my Bestiary model.
It moves randomly in the ocean.
It gets bigger each time step.
It dies (looses all its living behaviors):
- when it is caught by the castaway, or
- when it reaches old age, or
- randomly while swimming in the ocean (something eats it, or it's injured, etc.)
If caught by the castaway, a fish acquires a new behavior:
- it starts to decompose and the castaway must eat it before it "becomes bad"
Grid
----
I may want to stitch together 2 or more grids to create the overall IslandSystem.
- 2 grids with Island at the top and Ocean at the bottom; TB or BT or LR or RL
- 9 grids with Island inn the middle and parts of the Ocean in the 8 surrounding grids
- see [2] for one way to do this
- gridType can be
- "Gmt" NEIGHBORHOOD_MOORE (8 neighbors) + BOUNDARY_TORUS (boundaries wrap)
- "Gmg" NEIGHBORHOOD_MOORE (8 neighbors) + BOUNDARY_GRID
- OR just use one grid, where each gridCell contains an Ocean or Island building block
- similar to WallSection and other node types in Bestiary
- this approach would allow an island with any shape
custom Avatar behaviors
-----------------------
ava.append("<script>$wnd.console.log('TEST');</script>");
ava.append("<script>$wnd.console.log(this);</script>");
ava.append("<script>$wnd.console.log(this.parent());</script>");
ava.append('<script>
var ava = this.parent();
ava.action("build Lumber; take lumber;");
var node = ava.first();
if (node) {
if (node.xhc().name() == "Lumber") {
ava.action("build Hut role HomeSweetHome; eat lumber;");
}
}
</script>');
ava.append('<script>var ava=this.parent();ava.action("build Lumber;take lumber;");var node=ava.first();if(node){if(node.xhc().name()=="Lumber"){ava.action("build Hut role HomeSweetHome;eat lumber;");}}</script>');
ava.append('<script>var ava=this.parent();console.log(ava.name());ava.action("build Lumber;take lumber;");var node=ava.first();console.log(node.name());if(node){if(node.xhc().name()=="Lumber"){ava.action("build Hut role HomeSweetHome;eat lumber;");}}</script>');
// assume that Avatar has collected some lumber
var ava = xh.avatar();
ava.append('<script>var ava=this.parent();console.log(ava.name());var node=ava.first();console.log(node.name());if(node){if(node.xhc().name()=="Lumber"){ava.action("build Hut role HomeSweetHome;eat lumber;");}}</script>');
// could this somehow be in xh.avatarKeyMap, so it could be invoked with a single key?
ava.append('<script>var ava=this.parent();var node=ava.first();if(node){if(node.xhc().name()=="Lumber"){ava.action("build Hut role HomeSweetHome;eat lumber;");}}</script>');
// the following sort-of works
ava.action("if xpath(Lumber) build Hut role Shack; eat lumber;");
// this works
ava.action("if xpath(Avatar/Lumber) build Hut role Shack;");
ava.action("if xpath(Avatar/Lumber) build Hut role Shack;if xpath(Avatar/Lumber) eat lumber;");
Speech generation
-----------------
ava.action("out speech Hello");
ava.action("param speech true");
Speech recognition (only works with localhost)
------------------
xh.speechRecognition();
June 5, 2018
------------
I started Island 2, to implement the exact Minecraft (1.12.2) way of starting a game. [4]
Basically, in Minecraft:
- chop several trees (Birch or Oak or other(s)?) into 10 blocks
- move close to a tree until a block boundary appears
- hold down on the left mouse button until the block falls out of the tree
- take the block into inventory by moving close to it
- press E to engage with the inventory
- move tree blocks onto the built-in 2x2 crafting table
-
colors
------
these are the colors I used in Cube:
#b8ccea
#d0c883
#171c8f
#f1b434
#9cdbd9
#c2e189
TODO
----
- fix: Lumber has a Plantbehavior, which means it "rots" and gets removed when in the Avatar inventory
To view IDs of all records in Mongo Test02 database (in Firefox and Google Chrome):
---------------------------------------------------
var doccs = Test02.find().fetch(); // returns an array
doccs.forEach(function(docc) {
console.log(docc._id);
});
To delete all records from Mongo Test02 database (in Google Chrome):
------------------------------------------------
var doccs = Test02.find().fetch(); // returns an array
doccs.forEach(function(docc) {
Test02.remove(this._id); // doesn't work anymore
});
Test02.remove({_id:'GeCj4wWTYwnxyEcjZ'}); // this works
// this works
var doccs = Test02.find().fetch();
doccs.forEach(function(docc) {
var obj = {};
obj._id = docc._id;
console.log(obj);
Test02.remove(obj);
});
References
----------
(1) http://www.primordion.com/Xholon/gwt/wb/editwb.html?app=1f961eced0536248701adc9977faf43f&src=gist
) http://www.primordion.com/Xholon/gwt/Xholon.html?app=1f961eced0536248701adc9977faf43f&src=gist&gui=none
see ideas in this General Relativity workbook; uses GridGenerator
(2) http://www.primordion.com/Xholon/gwt/wb/editwb.html?app=8d4f8e4b85906690116a1787b90118cd&src=gist
) http://www.primordion.com/Xholon/gwt/XholonTether.html?app=8d4f8e4b85906690116a1787b90118cd&src=gist&gui=none
see ideas in this Cube workbook; multiple grids, uses GridGenerator 6 times, uses Tether JS library
implements Avatar movement between grids
(3) http://www.primordion.com/Xholon/gwt/wb/editwb.html?app=7381da240bf298a3db6d6112b4440fc2&src=gist
Xholon behavior subclasses
This workbook explores how to implement JavaScript classes and subclasses for Xholon behaviors.
(4) http://www.minecraftopia.com/how_to_play_minecraft
Upon entering a new world, the two most important things to do are crafting tools and building a shelter, all before the first night-cycle hits. Finding trees
and harvesting wood are the first steps towards making tools.
Once you have found a couple trees, use your fist to punch them and collect the wood that drops. To harvest resources, hold down the left mouse button
until the cracks in the block cause it to break. Once the block breaks, you can walk near it to automatically place the item in your inventory. Keep
punching trees until you have gathered 10 pieces of wood.
Now that you finished gathering wood, start looking for a place to build your night-one shelter. Keep in mind that your night-one shelter should be a
simple covering designed to keep monsters out. High up areas on top of mountains are usually a good pace to build, but anywhere will do.
Once you have identified a suitable location for your night-one shelter, it’s time to convert your wood into wooden planks. Press ‘E’ to open your inventory,
where you should notice the 2x2 crafting grid to the right of your character. When you place wood into the crafting squares, each piece of wood can be
turned into 4 wooden planks. Use the wood blocks you gathered to create 24 wooden planks.
Now that you have wooden planks, you can build your first crafting table. Crafting tables are the workbenches by which you will build most tools and
items in Minecraft, so be sure to place it in an accessible location.
Once your crafting table is placed, you can open it (right-click it) to reveal a 3x3 crafting grid, similar to the one in your inventory. Sticks are required to
build tools, so place two wooden planks in the crafting grid, one on top of the other. Use 6 of your wooden planks to create 12 sticks.
]]></Notes>
<params>
<!--<param name="RandomNumberSeed" value="200"/>--> <!-- DOES NOT WORK - the effect happens too late -->
<param name="ReadyForMeteor" value="false"/>
</params>
<_-.XholonClass>
<IslandSystem/>
<Ocean/>
<Island/>
<!-- environment -->
<Weather/>
<!-- types of food available to the castaway on the island -->
<!-- seafood from the ocean -->
<Fish/>
<!-- edible plants on the island -->
<Plant>
<Fruit/>
<Vegetables/>
</Plant>
<PlantBehaviors/>
<FishBehaviors/>
<AnimalBehaviors/> <!-- cats -->
<!-- building materials available to the castaway -->
<Lumber/> <!-- maybe driftwood or beams from a sunken ship or logs lying on the ground -->
<!-- things that can be built -->
<Hut/> <!-- a hut can be built out of lumber -->
<Raft/> <!-- TODO a raft can be built out of 2 lumber -->
<Islet/> <!-- TODO an islet can be built out of 10 of some building material (rocks?) -->
<!-- grid -->
<!-- Luke's stuff -->
<Cat/> <!-- for now, a Cat is a kind of Fish so it can use the existing FishMovebehavior -->
<Stick/>
<String/>
<Hook/>
<FishingRod/> <!-- craft out of a stick + a string + a hook -->
<!--<OceanCell>--> <!-- OceanCell is the default -->
<!--<LandCell/>--> <!-- for now LandCell has to be a subclass of OceanCell -->
<!--<CoastalCell/>
</OceanCell>-->
<IslandGridCell>
<OceanCell/> <!-- OceanCell is the default -->
<LandCell/>
<CoastalCell/>
</IslandGridCell>
<GridCellPattern superClass="Attribute_String"/>
<!-- Minecraft stuff -->
<Tree>
<AcaciaTree/>
<BirchTree/>
<DarkOakTree/>
<JungleTree/>
<OakTree/>
<SpruceTree/>
</Tree>
<!-- Oak, Spruce, Birch, Jungle, Acacia, and Dark Oak -->
<Wood>
<AcaciaWood/>
<BirchWood/>
<DarkOakWood/>
<JungleWood/>
<OakWood/>
<SpruceWood/>
</Wood>
<Leaves/>
<Stump/>
<!-- Island Control Centre -->
<City/>
<University/>
<Library/>
<CoffeeShop/>
<IslandControlCentre/>
<!-- recipes, Minecraft-style recipes see Recipe mech and service -->
<!--<RecipeBookx superClass="Attribute_Object">
<MinecraftStyleRecipeBookx/>
</RecipeBookx>-->
<!-- an artifact that provides some useful items for free, for now -->
<TreasureChest/>
<TreasureChests/>
<!-- a node I can create to test <Symbol>js:...</Symbol> -->
<Jackal/>
<!-- use TestTool to test the Avatar apply command; TestTool has to be a GWT behavior -->
<TestTool superClass="Script"/>
</_-.XholonClass>
<xholonClassDetails>
<LandCell><Color>PaleGoldenRod</Color></LandCell> <!-- PaleGoldenRod -->
<CoastalCell><Color>#d0c883</Color></CoastalCell> <!-- LightSeaGreen #d6d6ad Cube: #b8ccea(lightblue) #d0c883(olive) #171c8f(darkblue) #f1b434(orange) #9cdbd9(lightblue) #c2e189(greenish) -->
<Avatar><Color>red</Color></Avatar>
<OakTree><DefaultContent><![CDATA[
<_-.oakdc>
<OakWood maxClones="6"/>
<Leaves maxClones="16"/>
<Stump/>
</_-.oakdc>
]]></DefaultContent></OakTree>
<BirchTree><DefaultContent><![CDATA[
<_-.birchdc>
<BirchWood maxClones="6"/>
<Leaves maxClones="16"/>
<Stump/>
</_-.birchdc>
]]></DefaultContent></BirchTree>
<TreasureChest><DefaultContent><![CDATA[
<_-.tcdc>
<Stick/>
<String/>
<Hook/>
</_-.tcdc>
]]></DefaultContent></TreasureChest>
<Lumber>
<!-- Symbol + Color -->
<Symbol>Triangle</Symbol>
<Color>Sienna</Color>
<!-- Icon + Color (same color as LandCell; this works but it flickers and adds a new img to body each time step) -->
<!--<Color>PaleGoldenRod</Color>
<Icon>data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfElEQVR42mNgIAOYawr8h2GyNLelqv0vjVAk3QBkzSCaJAOGgGZtBZ7/IEy2zSDN7mYicEPIcjZIc6SzJNgQsvyMbABZAYZuCHqYEASeZqL/M/zk/sMMQQ4TojR3pqv/15Dj/o8cKwQNgSkE2QzTTCh6cfqZnJwJt4FcAwDuFoevgpHrfgAAAABJRU5ErkJggg==</Icon>--> <!-- Minecraft wooden_sword image, from texture_content.json -->
</Lumber>
<Fish><Symbol>LRTriangle</Symbol><Color>SteelBlue</Color></Fish> <!-- Tuna silver,SteelBlue -->
<OakTree><Symbol>Rectangle</Symbol><Color>Green</Color></OakTree>
<BirchTree><Symbol>Circle</Symbol><Color>Olive</Color></BirchTree>
<OakWood><Symbol>SmallRectangle</Symbol><Color>DarkGreen</Color></OakWood>
<BirchWood><Symbol>SmallCircle</Symbol><Color>DarkOliveGreen</Color></BirchWood>
<Fruit><Symbol>Cross</Symbol><Color>Orange</Color></Fruit>
<Vegetables><Symbol>ReverseTriangle</Symbol><Color>Violet</Color></Vegetables>
<Cat><Symbol>Wye</Symbol><Color>black</Color></Cat>
<City>
<Color>gold</Color>
<!--<Symbol>js:ctx.fillStyle='rgba(255,0,0,0.5)';ctx.fillRect(x,y,cellSize,cellSize);</Symbol> this works -->
<Symbol>js:ctx.fillRect(x+1,y+1,cellSize-2,cellSize-2);</Symbol> <!-- this works; it uses the fillStyle specified in <Color> -->
<!--<Symbol>js:ctx.beginPath();ctx.moveTo(x+cellSize*0.5,y+cellSize*0.5);ctx.lineTo(x+cellSize,y+cellSize);ctx.lineTo(x,y+cellSize);ctx.closePath();ctx.fill();</Symbol>--> <!-- this works -->
</City>
<Hut>
<Color>DarkGoldenRod</Color>
<!--<Symbol>js:ctx.fillRect(x,y,3,3);ctx.fillRect(x+5,y,3,3);ctx.fillRect(x,y+5,3,3);ctx.fillRect(x+5,y+5,3,3);</Symbol>--> <!-- this works -->
<Symbol>
js:ctx.fillStyle='rgba(255,0,0,1.0)';ctx.fillRect(x,y,3,3);
ctx.fillStyle='rgba(0,255,0,1.0)';ctx.fillRect(x+5,y,3,3);
ctx.fillStyle='rgba(0,0,255,1.0)';ctx.fillRect(x,y+5,3,3);
ctx.fillStyle='rgba(255,255,0,1.0)';ctx.fillRect(x+5,y+5,3,3);
</Symbol> <!-- this works -->
</Hut>
<TreasureChest>
<Color>Fuchsia</Color>
<Symbol>js:ctx.fillRect(x+1,y+1,cellSize-2,cellSize-2);</Symbol>
</TreasureChest>
<Jackal>
<Color>purple</Color>
<Symbol>js:ctx.fillRect(x+1,y+1,cellSize-2,cellSize-2);</Symbol>
</Jackal>
<TestTool><DefaultContent><![CDATA[
var me, beh = {
postConfigure: function() {
me = this.cnode;
$wnd.console.log(me.name());
},
processReceivedSyncMessage: function(msg) {
var data = msg.data;
$wnd.console.log(data);
var str = "TestTool received message";
if (data && (data.length)) {
for (var i = 0; i < data.length; i++) {
str += " " + data[i];
}
}
return str;
}
}
]]></DefaultContent></TestTool>
</xholonClassDetails>
<IslandSystem>
<!-- rows and cols must be same as const ROWS and const COLS in Behaviors -->
<GridGenerator rows="80" cols="120" gridType="Gmt" names="Space,FieldRow,OceanCell" columnColor="171c8f" gridViewerParams="IslandSystem/Space,8,Island Viewer,true" cellsCanSupplyOwnColor="true"> <!-- columnColor 000088 -->
<Attribute_String>TODO CellPattern ?</Attribute_String>
</GridGenerator>
<!-- L = LandCell c = CoastalCell -->
<GridCellPattern xpos="20" ypos="15"><![CDATA[
..CCCCCCCCCCCC
..CLLCLLLCCLLC
CCCCLLLLLLLLCCCC
CLLLLLLLLLLLLLLC
CLLLLLLLLLLLLLLC
CCCCLLLLLLLLLCCC
..CCCCCLLLLCCC
..CLL.LLLLLLC
.CCCLLLLLLLLC
.CLLLLLLLLLLCCC
.CCLLLLLLLLLLLCCCCCCCCC
..CCCLLLLLLLLLLLLLLLLLC
...CLLLLLLLLLLLLLLLLCCC
...CCCLLLLLLLLLLLLLCC
...CLLLLLLLLLCCCCCCC
..CCCCCLLLLCCC
..CLL.LLLLLLLC
CCCCLLLLLLLLCCCC
CLLLLLLLLLLLLLLC
CLLLLLLLLLLLLLLC
CCCCLLLLLLLLLCCC
...CCCCLLLLCCC
......CCCCCC
]]></GridCellPattern>
<GridCellPattern xpos="50" ypos="40"><![CDATA[
..........CCCCC.CCC..CCCCCCC
.........CCLCLCCCLCCCCLCCLLCC
........CCCLLLLLLLLLLLLLLLLLC
......CCCLLLLLLLLLLLLLLLLLCCC
......CLLLLLLLLLLLLLLLLLCCC
..CCCCCCLLLLLLLLLLLLLLLLLLCC
CCCLLLLLLLLLLLLLLLLLLLLLLLLCCC
CLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCCCCCC
CCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCC
.CCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLC
..CCCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCCCC
...CLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCC
...CCCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCC
...CLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCCC
...CCCCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCC
......CCCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLC
.......CLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCC
.......CCCLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCC
.......CLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLCCCC
.......CCCCCCCLLLLLLLLLLLLLLLLLLLLLCCCC
............CLLLLLLLLLLLLLLLLLLLLLLLC
............CCCLLLCCCCCCCCCCCCLLLLCCC
..............CCCCC..........CCCCCC
]]></GridCellPattern>
<!-- each PlantBehavior and FishBehavior node moves itself into one of these containers at runtime -->
<PlantBehaviors/>
<FishBehaviors/>
<AnimalBehaviors/>
<!-- see Xml2Xholon - DefaultContent only works if I include RoomModel somewhere before I need to use DefaultContent -->
<RoomModel/>
<Ocean>
<Fish multiplicity="100"/> <!-- 30 -->
<Island>
<Fruit multiplicity="10"/>
<Vegetables multiplicity="10"/>
<Lumber multiplicity="10"/>
<Cat roleName="Licorice"/>
<!--<BirchTree multiplicity="20"/>-->
<!-- TODO multiplicity causes DefaultContent content to be duplicated in each instance node -->
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<BirchTree/>
<!--<OakTree multiplicity="5"/>-->
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<OakTree/>
<City roleName="Ottawa">
<University roleName="Carleton">
<Library>
<CoffeeShop roleName="Starbucks">
<IslandControlCentre/>
</CoffeeShop>
</Library>
</University>
</City>
<TreasureChests>
<TreasureChest/>
<TreasureChest/>
<TreasureChest/>
<TreasureChest/>
<TreasureChest/>
</TreasureChests>
</Island>
</Ocean>
<Weather state="sunny and windy"/>
<!-- based on the JSON style in recipes.json
~/JavascriptThirdParty/minecraft/minecraft-data-master/data/pc/1.12/recipes.json
http://minecraft-data.prismarine.js.org/?v=1.12.2&d=recipes
If I want to make a FishingRod, then I must have one Stick + one String + one Hook.
To access:
//var rbook = temp1.obj();
var $wnd = window;
var rbook = $wnd.xh.root().xpath("IslandSystem/MinecraftStyleRecipeBook").obj();
var hut = rbook["Hut"][0];
var ingr1 = hut.ingredients[0];
var $wnd = window;
var me = $wnd.xh.root();
var recipeService = $wnd.xh.service("RecipeService");
$wnd.console.log(recipeService);
var data = "RecipeService-MinecraftStyleRecipeBook-Island";
$wnd.console.log(data);
var msg = recipeService.call(-3897, data, me); // SIG_GET_RECIPE_BOOK_REQ
$wnd.console.log(msg);
var data2 = ["RecipeService-MinecraftStyleRecipeBook-Island", "Hut"];
var msg2 = recipeService.call(-3896, data2, me); // SIG_GET_RECIPE_REQ
$wnd.console.log(msg2);
$wnd.console.log(msg2.data);
$wnd.console.log(msg2.data.length);
$wnd.console.log(msg2.data[0]);
var data3 = ["RecipeService-MinecraftStyleRecipeBook-Island", "FishingRod"];
var msg3 = recipeService.call(-3896, data3, me); // SIG_GET_RECIPE_REQ
$wnd.console.log(msg3.data[0]);
-->
<MinecraftStyleRecipeBook roleName="Island"><Attribute_String><![CDATA[
{
"FishingRod": [
{
"ingredients": [
"Stick",
"String",
"Hook"
],
"result": {
"multiplicity": 1,
"xhc": "FishingRod"
}
}
],
"Hut": [
{
"ingredients": [
"Lumber"
],
"result": {
"multiplicity": 1,
"xhc": "Hut",
"role": "Cottage"
}
}
]
}
]]></Attribute_String></MinecraftStyleRecipeBook>
<!--<TestTool/> have Avatar build this -->
<!-- Prevent children and siblings from running their act(), to prevent navigating through the large grid each timestep. -->
<ActRegulator val="1.0"/>
<!-- the Space grid is inserted here at runtime -->
</IslandSystem>
<IslandSystembehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
const ROWS = 80; // same as value in GridGenerator
const COLS = 120;
//$wnd.xh.param("RandomNumberSeed", "123"); // the effect happens too late
$wnd.xh.seed(200); // 200 12345
$wnd.xh.param("TimeStepInterval","100"); // "500" "100"
$wnd.xh.param("AppM","true");
// position and set commands for built-in Avatar
// "x" prevents exiting from a Cell node
$wnd.xh.avatarKeyMap('{"SHIFT":"true","UP":"go port0;if xpath(Avatar/ancestor::OceanCell) go port2;","DOWN":"go port2;if xpath(Avatar/ancestor::OceanCell) go port0;","LEFT":"if xpath(preceding-sibling::OceanCell) wait else prev","RIGHT":"if xpath(following-sibling::OceanCell) wait else next","a":"appear","D":"drop","d":"drop first","e":"eat","f":"follow prev","F":"unfollow","g":"recipe FishingRod;take fishingRod;","h":"if xpath(Avatar/Lumber) build Hut role Shack;if xpath(Avatar/Lumber) unbuild lumber;","i":"inventory","J":"build Jackal","k":"enter *Tree;takeclone *Wood;exit;","l":"look","L":"look all","n":"enter nextprev","p":"pause","r":"start","s":"step"," ":"step","T":"take","t":"take nextprev","v":"vanish","w":"who;where;","x":"if xpath(../../FieldRow) wait else exit","z":"param transcript toggle;","<":"flip prev",">":"flip next",",":"flip prev",".":"flip next","0":"out transcript ZERO","1":"out transcript ONE","2":"out transcript TWO"}');
var ava = $wnd.xh.avatar();
ava.action('enter;enter space_;enter;enter;appear;param transcript true;');
ava.action('param meteor true;');
//ava.action('param meteormove true;');
ava.action('param recipebook Island;');
// Add a TestTool to Avatar's inventory
//ava.action("build TestTool; take testTool;");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify Plant behavior
$wnd.xh.Plantbehavior = function Plantbehavior() {}
$wnd.xh.Plantbehavior.prototype.postConfigure = function() {
this.plant = this.cnode.parent();
this.plant.calories = 0;
this.plant.xpath("ancestor::IslandSystem/PlantBehaviors").append(this.cnode.remove());
};
$wnd.xh.Plantbehavior.prototype.act = function() {
//this.plant.println("I am " + this.plant.name() + " calories:" + this.plant.calories);
if (this.plant.parent() == null) {
// I've been eaten, so remove this behavior from the simulation
this.cnode.remove();
}
else if (this.plant.parent().xhc().name() == "Avatar") {
// I've been picked
this.plant.calories--;
if (this.plant.calories <= 0) {
// I've gone bad
this.plant.remove();
this.cnode.remove();
}
}
else if (this.plant.parent().xhc().name() == "Island") {
this.plant.calories++;
this.moveSelfToGrid();
}
else {
this.plant.calories++;
}
};
$wnd.xh.Plantbehavior.prototype.moveSelfToGrid = function() {
// DO NOT run this code in postConfigure(); it prevents a next Plant node from obtaining a Plantbehavior
// move this.plant to a random position within the land part of the grid
var ix = $wnd.Math.floor($wnd.xh.random() * landCellArr.length);
var fcell = landCellArr[ix];
fcell.append(this.plant.remove());
};
// specify Fruit behavior
$wnd.xh.Fruitbehavior = function Fruitbehavior() {};
$wnd.xh.Fruitbehavior.prototype = $wnd.Object.create($wnd.xh.Plantbehavior.prototype);
// specify Vegetables behavior
$wnd.xh.Vegetablesbehavior = function Vegetablesbehavior() {};
$wnd.xh.Vegetablesbehavior.prototype = $wnd.Object.create($wnd.xh.Plantbehavior.prototype);
// specify Lumber behavior
$wnd.xh.Lumberbehavior = function Lumberbehavior() {};
$wnd.xh.Lumberbehavior.prototype = $wnd.Object.create($wnd.xh.Plantbehavior.prototype);
// specify BirchTree behavior
$wnd.xh.BirchTreebehavior = function BirchTreebehavior() {};
$wnd.xh.BirchTreebehavior.prototype = $wnd.Object.create($wnd.xh.Plantbehavior.prototype);
// specify OakTree behavior
$wnd.xh.OakTreebehavior = function OakTreebehavior() {};
$wnd.xh.OakTreebehavior.prototype = $wnd.Object.create($wnd.xh.Plantbehavior.prototype);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify Fish Grow behavior
$wnd.xh.FishGrowbehavior = function FishGrowbehavior() {}
$wnd.xh.FishGrowbehavior.prototype.postConfigure = function() {
this.fish = this.cnode.parent();
this.fish.calories = 0;
this.fish.xpath("ancestor::IslandSystem/FishBehaviors").append(this.cnode.remove());
};
$wnd.xh.FishGrowbehavior.prototype.act = function() {
//this.fish.println("I am " + this.fish.name() + " calories:" + this.fish.calories);
if (this.fish.parent() == null) {
// I've been eaten, so remove this behavior from the simulation
this.cnode.remove();
}
else if (this.fish.parent().xhc().name() == "Avatar") {
// I've been caught
this.fish.calories--;
if (this.fish.calories <= 0) {
// I've gone bad
this.fish.remove();
this.cnode.remove();
}
}
else if (this.fish.parent().xhc().name() == "Ocean") {
this.fish.calories++;
//this.moveSelfToGrid();
}
else if (this.fish.parent().xhc().name() == "OceanCell") {
this.fish.calories++;
//this.moveSelfToGrid();
}
else {
// I've probably been caught and am now somewhere on land in a hut, or maybe in a boat
this.fish.calories--;
if (this.fish.calories <= 0) {
// I've gone bad :-(
this.fish.remove();
this.cnode.remove();
}
}
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify Fish Move behavior
$wnd.xh.FishMovebehavior = function FishMovebehavior() { // (destCellTypeNot) {
//$wnd.xh.FishMovebehavior.destCellTypeNot = destCellTypeNot;
}
$wnd.xh.FishMovebehavior.prototype.postConfigure = function() {
this.fish = this.cnode.parent();
this.fish.xpath("ancestor::IslandSystem/FishBehaviors").append(this.cnode.remove());
};
$wnd.xh.FishMovebehavior.prototype.act = function() {
//this.fish.println("I am " + this.fish.name() + " moving");
if (this.fish.parent() == null) {
// I've been eaten, so remove this behavior from the simulation
this.cnode.remove();
return;
}
var pname = this.fish.parent().xhc().name();
if (pname == "Ocean") {
this.moveSelfToGrid();
}
else if ((pname == "OceanCell") || (pname == "CoastalCell")) {
// move randomly in the grid
if (!this.nibble()) {
this.move();
}
}
else if (pname == "Avatar") {
// I've been caught, so don't move
}
else {
//$wnd.console.log("ERROR " + this.fish.parent().name()); // Hut, LandCell, etc.
}
};
$wnd.xh.FishMovebehavior.prototype.moveSelfToGrid = function() {
// DO NOT run this code in postConfigure(); it prevents a next Fish node from obtaining a Fishbehavior
// move this.fish to a random position within the ocean part of the grid
var ix = $wnd.Math.floor($wnd.xh.random() * oceanCellArr.length);
var fcell = oceanCellArr[ix];
fcell.append(this.fish.remove());
};
$wnd.xh.FishMovebehavior.prototype.nibble = function() {
// a fish nibbles everything it's near, to see if it's food
// there's a higher probability of stopping to nibble if the Avatar has a FishingRod, than if the Avatar has no FishingRod
var neighbor = this.fish.prev();
if (!neighbor) {return false;}
var rnum = $wnd.xh.random();
var fishingRod = null;
var nname = neighbor.xhc().name();
switch (nname) {
case "Avatar": // possibly nibble the avatar/player
//this.fish.println("rnum: " + rnum);
fishingRod = neighbor.xpath("FishingRod");
if (fishingRod) {
if (rnum > 0.99) { // 0.9
return false;
}
}
else {
if (rnum > 0.9) { // 0.5
return false;
}
}
break;
//case "FishingRod":
// //this.fish.println("rnum: " + rnum);
// if (rnum > 0.99) { // 0.9
// return false;
// }
// break;
default:
//this.fish.println(this.fish.name() + " is co-located with " + neighbor.name());
return false;
}
this.fish.println(this.fish.name() + " is nibbling a " + nname + (fishingRod ? " who is using a fishing rod" : ""));
// become the first child in the current cell, making it possible for the Avatar to "take prev;"
//this.fish.parent().prepend(this.fish.remove());
return true;
};
$wnd.xh.FishMovebehavior.prototype.move = function() {
var foundNewLocation = false;
var count = 0;
while ((!foundNewLocation) && (count < 1)) { // 10
var moveX = $wnd.Math.floor($wnd.xh.random() * 3) - 1;
var moveY = $wnd.Math.floor($wnd.xh.random() * 3) - 1;
if ((moveX == 0) && (moveY == 0)) {
return;
}
var portX = -1;
var portY = -1;
if (moveX > 0) {
portX = 1; //IGrid.P_EAST
}
else {
portX = 3; //IGrid.P_WEST
}
if (moveY > 0) {
portY = 0; //IGrid.P_NORTH
}
else {
portY = 2; //IGrid.P_SOUTH
}
count++;
var destination = this.fish.parent();
if (moveX != 0) {
destination = destination.port(portX);
}
if (moveY != 0) {
destination = destination.port(portY);
}
if (destination && (destination.xhc().name() != "LandCell")) { //$wnd.xh.FishMovebehavior.destCellTypeNot)) {
destination.append(this.fish.remove());
foundNewLocation = true;
}
}
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify Cat Move behavior
$wnd.xh.CatMovebehavior = function CatMovebehavior() {}
$wnd.xh.CatMovebehavior.prototype.postConfigure = function() {
this.cat = this.cnode.parent();
this.cat.xpath("ancestor::IslandSystem/AnimalBehaviors").append(this.cnode.remove());
};
$wnd.xh.CatMovebehavior.prototype.act = function() {
//this.cat.println("I am " + this.cat.name() + " moving");
if (this.cat.parent() == null) {
// I've been eaten, so remove this behavior from the simulation
this.cnode.remove();
}
else if (this.cat.parent().xhc().name() == "Island") {
this.moveSelfToGrid();
}
else if (this.cat.parent().xhc().name().endsWith("Cell")) { // FieldCell OceanCell LandCell
// move randomly in the grid
this.move();
}
else if (this.cat.parent().xhc().name() == "Avatar") {
// I've been caught, so don't move
}
else {
$wnd.console.log("ERROR " + this.cat.parent().name());
}
};
$wnd.xh.CatMovebehavior.prototype.moveSelfToGrid = function() {
// DO NOT run this code in postConfigure(); it prevents a next Cat node from obtaining a Catbehavior
// move this.cat to a random position within the ocean part of the grid
var ix = $wnd.Math.floor($wnd.xh.random() * landCellArr.length);
var fcell = landCellArr[ix];
fcell.append(this.cat.remove());
};
$wnd.xh.CatMovebehavior.prototype.move = function() {
var foundNewLocation = false;
var count = 0;
while ((!foundNewLocation) && (count < 1)) { // 10
var moveX = $wnd.Math.floor($wnd.xh.random() * 3) - 1;
var moveY = $wnd.Math.floor($wnd.xh.random() * 3) - 1;
if ((moveX == 0) && (moveY == 0)) {
return;
}
var portX = -1;
var portY = -1;
if (moveX > 0) {
portX = 1; //IGrid.P_EAST
}
else {
portX = 3; //IGrid.P_WEST
}
if (moveY > 0) {
portY = 0; //IGrid.P_NORTH
}
else {
portY = 2; //IGrid.P_SOUTH
}
count++;
var destination = this.cat.parent();
if (moveX != 0) {
destination = destination.port(portX);
}
if (moveY != 0) {
destination = destination.port(portY);
}
if (destination && (destination.xhc().name() != "OceanCell")) {
destination.append(this.cat.remove());
foundNewLocation = true;
}
}
};
var oceanCellArr = [];
var landCellArr = [];
var coastalCellArr = [];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify behavior to add all Cell nodes into class-specific arrays, for use by moveSelfToGrid functions
// position system Avatar
$wnd.xh.CellArraybehavior = function CellArraybehavior() {}
$wnd.xh.CellArraybehavior.prototype.postConfigure = function() {
this.isys = this.cnode.parent();
var space = this.isys.xpath("Space");
var row = space.first();
while (row) {
var cell = row.first();
while (cell) {
switch (cell.xhc().name()) {
case "OceanCell":
oceanCellArr.push(cell);
break;
case "LandCell":
landCellArr.push(cell);
break;
case "CoastalCell":
coastalCellArr.push(cell);
break;
default: break;
}
cell = cell.next();
}
row = row.next();
}
//ava.action('go xpath()');
// each Avatar should go in it's own random coastalCell, so use Math.random() rather than xh.random()
var ix = $wnd.Math.floor($wnd.Math.random() * coastalCellArr.length);
var fcell = coastalCellArr[ix];
fcell.append(ava.remove());
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify City behavior
$wnd.xh.Citybehavior = function Citybehavior() {}
$wnd.xh.Citybehavior.prototype.postConfigure = function() {
this.city = this.cnode.parent();
//this.plant.calories = 0;
//this.plant.xpath("ancestor::IslandSystem/PlantBehaviors").append(this.cnode.remove());
var ix = $wnd.Math.floor($wnd.xh.random() * coastalCellArr.length);
var ccell = coastalCellArr[ix];
ccell.append(this.city.remove());
this.cnode.remove();
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// specify TreasureChests behavior
$wnd.xh.TreasureChestsbehavior = function TreasureChestsbehavior() {}
$wnd.xh.TreasureChestsbehavior.prototype.postConfigure = function() {
this.treasureChests = this.cnode.parent();
var tchest = this.treasureChests.first();
while (tchest && tchest.xhc().name() == "TreasureChest") {
var ix = $wnd.Math.floor($wnd.xh.random() * coastalCellArr.length);
var ccell = coastalCellArr[ix];
var tchestNext = tchest.next();
ccell.append(tchest.remove());
tchest = tchestNext;
}
this.cnode.remove();
};
//# sourceURL=IslandSystembehavior.js
]]></IslandSystembehavior>
<Fruitbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.Fruitbehavior();
//# sourceURL=Fruitbehavior.js
]]></Fruitbehavior>
<Vegetablesbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.Vegetablesbehavior();
//# sourceURL=Vegetablesbehavior.js
]]></Vegetablesbehavior>
<Lumberbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.Lumberbehavior();
//# sourceURL=Lumberbehavior.js
]]></Lumberbehavior>
<BirchTreebehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.BirchTreebehavior();
//# sourceURL=BirchTreebehavior.js
]]></BirchTreebehavior>
<OakTreebehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.OakTreebehavior();
//# sourceURL=OakTreebehavior.js
]]></OakTreebehavior>
<Fishbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.FishGrowbehavior();
//# sourceURL=FishGrowbehavior.js
]]></Fishbehavior>
<Fishbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.FishMovebehavior(); //("LandCell");
//# sourceURL=FishMovebehavior.js
]]></Fishbehavior>
<Catbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.CatMovebehavior();
//# sourceURL=CatMovebehavior.js
]]></Catbehavior>
<GridCellPatternbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, beh = {
postConfigure: function() {
me = this.cnode.parent();
this.cnode.remove();
//me.println("xpos:" + me.xpos + " ypos:" + me.ypos);
var gcpstr = me.text().trim();
var gcparr = gcpstr.split("\n");
var row = me.xpath("../Space/FieldRow[" + me.ypos + "]");
var fcol = row.xpath("OceanCell[" + me.xpos + "]");
var col = fcol;
for (var i = 0; i < gcparr.length; i++) {
var gcpline = gcparr[i].trim();
//me.println(gcpline);
for (var j = 0; j < gcpline.length; j++) {
switch (gcpline[j]) {
case "L":
col.xhc("LandCell");
break;
case "C":
col.xhc("CoastalCell");
break;
default: // "."
break;
}
col = col.next();
}
fcol = fcol.port(2);
col = fcol;
}
}
}
//# sourceURL=GridCellPatternbehavior.js
]]></GridCellPatternbehavior>
<IslandSystembehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.CellArraybehavior();
//# sourceURL=IslandSystembehavior2.js
]]></IslandSystembehavior>
<Citybehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.Citybehavior();
//# sourceURL=Citybehavior.js
]]></Citybehavior>
<TreasureChestsbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var beh = new $wnd.xh.TreasureChestsbehavior();
//# sourceURL=TreasureChestsbehavior.js
]]></TreasureChestsbehavior>
<IslandControlCentrebehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, count, beh = {
postConfigure: function() {
me = this.cnode.parent();
count = 0;
//this.cnode.remove();
//$wnd.console.log("IslandControlCentrebehavior starting...");
},
act: function() {
// don't let Meteor start until the app has a chance to deploy everything to their initial/default GridCells
if (count < 2) {
//$wnd.console.log("IslandControlCentrebehavior waiting...");
count++;
}
else if (count >= 2) {
//$wnd.console.log("IslandControlCentrebehavior ReadyForMeteor true");
$wnd.xh.param("ReadyForMeteor","true");
this.cnode.remove();
}
}
}
//# sourceURL=IslandControlCentrebehavior.js
]]></IslandControlCentrebehavior>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<svg width="160" height="10" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Ocean</title>
<rect id="IslandSystem/Ocean" fill="#98FB98" height="10" width="50" x="0" y="0"/>
<g>
<title>Island</title>
<rect id="IslandSystem/Ocean/Island" fill="#6AB06A" height="10" width="10" x="55" y="0"/>
</g>
<g>
<title>PlantBehaviors</title>
<rect id="IslandSystem/PlantBehaviors" fill="orange" height="10" width="10" x="75" y="0"/>
</g>
<g>
<title>FishBehaviors</title>
<rect id="IslandSystem/FishBehaviors" fill="orange" height="10" width="10" x="95" y="0"/>
</g>
<g>
<title>MinecraftStyleRecipeBook</title>
<rect id="IslandSystem/MinecraftStyleRecipeBook" fill="blue" height="10" width="10" x="115" y="0"/>
</g>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>
<GridCellPattern xpos="90" ypos="5"><![CDATA[
..CCCCCCCCCCCC
..CLLCLLLCCLLC
CCCCLLLLLLLLCCCC
CLLLLLLLLLLLLLLC
CLLLLLLLLLLLLLLC
CCCCLLLLLLLLLCCC
..CCCCCLLLLCCC
..CLL.LLLLLLC
.CCCLLLLLLLLC
.CLLLLLLLLLLCCC
.CCLLLLLLLLLLLCCCCCCCCC
..CCCLLLLLLLLLLLLLLLLLC
...CLLLLLLLLLLLLLLLLCCC
...CCCLLLLLLLLLLLLLCC
...CLLLLLLLLLCCCCCCC
..CCCCCLLLLCCC
..CLL.LLLLLLLC
CCCCLLLLLLLLCCCC
CLLLLLLLLLLLLLLC
CLLLLLLLLLLLLLLC
CCCCLLLLLLLLLCCC
...CCCCLLLLCCC
......CCCCCC
]]>
<GridCellPatternbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, beh = {
postConfigure: function() {
me = this.cnode.parent();
this.cnode.remove();
//me.println("xpos:" + me.xpos + " ypos:" + me.ypos);
var gcpstr = me.text().trim();
var gcparr = gcpstr.split("\n");
var row = me.xpath("ancestor::Space/FieldRow[" + me.ypos + "]");
var fcol = row.xpath("OceanCell[" + me.xpos + "]");
var col = fcol;
for (var i = 0; i < gcparr.length; i++) {
var gcpline = gcparr[i].trim();
//me.println(gcpline);
for (var j = 0; j < gcpline.length; j++) {
switch (gcpline[j]) {
case "L":
col.xhc("LandCell");
break;
case "C":
col.xhc("CoastalCell");
break;
default: // "."
break;
}
col = col.next();
}
fcol = fcol.port(2);
col = fcol;
}
me.remove();
}
}
]]></GridCellPatternbehavior>
</GridCellPattern>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment