Last active
June 2, 2018 12:50
-
-
Save kenwebb/c8e4d796b9d76021d677a1d712ecadae to your computer and use it in GitHub Desktop.
Island 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Sat Jun 02 2018 08:50:31 GMT-0400 (EDT)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: Island 1 | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 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 | |
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(); | |
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. | |
]]></Notes> | |
<_-.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/> | |
<!-- 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 --> | |
<!--<FieldCell> | |
<OceanCell/> | |
<LandCell/> | |
</FieldCell>--> | |
<OceanCell> <!-- OceanCell is the default --> | |
<LandCell/> <!-- for now LandCell has to be a subclass of OceanCell --> | |
</OceanCell> | |
<GridCellPattern superClass="Attribute_String"/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
<LandCell><Color>orange</Color></LandCell> | |
</xholonClassDetails> | |
<IslandSystem> | |
<!-- rows and cols must be same as const ROWS and const COLS in Behaviors --> | |
<GridGenerator rows="100" cols="100" gridType="Gmt" names="Space,FieldRow,OceanCell" columnColor="000088" gridViewerParams="IslandSystem/Space,8,Island Viewer,true" cellsCanSupplyOwnColor="true"> | |
<Attribute_String>TODO CellPattern ?</Attribute_String> | |
</GridGenerator> | |
<!-- L = LandCell --> | |
<GridCellPattern xpos="20" ypos="25"> | |
..LL.LLL..LL.. | |
...LLLLLLLL... | |
LLLLLLLLLLLLLL | |
LLLLLLLLLLLLLL | |
...LLLLLLLLL.. | |
......LLLL.... | |
..LL.LLLLLL.. | |
...LLLLLLLL... | |
.LLLLLLLLLL... | |
..LLLLLLLLLLL. | |
....LLLLLLLLLLLLLLLLL | |
...LLLLLLLLLLLLLLLL | |
.....LLLLLLLLLLLLL | |
...LLLLLLLLL.. | |
......LLLL.... | |
..LL.LLLLLLL.. | |
...LLLLLLLL... | |
LLLLLLLLLLLLLL | |
LLLLLLLLLLLLLL | |
...LLLLLLLLL.. | |
......LLLL.... | |
</GridCellPattern> | |
<!-- each PlantBehavior and FishBehavior node moves itself into one of these containers at runtime --> | |
<PlantBehaviors/> | |
<FishBehaviors/> | |
<Ocean> | |
<Fish multiplicity="20"/> | |
<Cat roleName="Licorice"/> | |
<Island> | |
<Fruit multiplicity="5"/> | |
<Vegetables multiplicity="5"/> | |
<Lumber multiplicity="20"/> | |
</Island> | |
</Ocean> | |
<Weather state="sunny and windy"/> | |
<!-- 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 = 100; // same as value in GridGenerator | |
const COLS = 100; | |
$wnd.xh.param("TimeStepInterval","500"); | |
$wnd.xh.param("AppM","true"); | |
// position and set commands for built-in Avatar | |
$wnd.xh.avatarKeyMap('{"UP":"go port0","DOWN":"go port2","LEFT":"go port3","RIGHT":"go port1","A":"appear","D":"drop","E":"eat","F":"flip","H":"if xpath(Avatar/Lumber) build Hut role Shack;if xpath(Avatar/Lumber) eat lumber;","I":"inventory","L":"look","N":"enter","P":"pause","R":"start","S":"step","T":"take","V":"vanish","W":"who;where;","X":"exit","Z":"param transcript toggle;"}'); | |
var ava = $wnd.xh.avatar(); | |
ava.action('enter;enter space_;enter;enter;appear;param transcript true;'); | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// 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 grid | |
var xpos = this.plant.xpos || $wnd.Math.ceil($wnd.Math.random() * COLS); | |
var ypos = this.plant.ypos || $wnd.Math.ceil($wnd.Math.random() * ROWS); | |
var fcell = $wnd.xh.root().xpath("descendant::Space/FieldRow[" + ypos + "]/OceanCell[" + xpos + "]"); | |
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 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 { | |
this.fish.calories++; | |
} | |
}; | |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
// specify Fish Move behavior | |
$wnd.xh.FishMovebehavior = function FishMovebehavior() {} | |
$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(); | |
} | |
else if (this.fish.parent().xhc().name() == "Ocean") { | |
this.moveSelfToGrid(); | |
} | |
else if (this.fish.parent().xhc().name().endsWith("Cell")) { // FieldCell OceanCell LandCell | |
// move randomly in the grid | |
this.move(); | |
} | |
else if (this.fish.parent().xhc().name() == "Avatar") { | |
// I've been caught, so don't move | |
} | |
else { | |
$wnd.console.log("ERROR " + this.fish.parent().name()); | |
} | |
}; | |
$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 grid | |
var xpos = this.fish.xpos || $wnd.Math.ceil($wnd.Math.random() * COLS); | |
var ypos = this.fish.ypos || $wnd.Math.ceil($wnd.Math.random() * ROWS); | |
var fcell = $wnd.xh.root().xpath("descendant::Space/FieldRow[" + ypos + "]/OceanCell[" + xpos + "]"); | |
fcell.append(this.fish.remove()); | |
}; | |
$wnd.xh.FishMovebehavior.prototype.move = function() { | |
var foundNewLocation = false; | |
var count = 0; | |
while ((!foundNewLocation) && (count < 10)) { | |
var moveX = $wnd.Math.floor($wnd.Math.random() * 3) - 1; | |
var moveY = $wnd.Math.floor($wnd.Math.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.append(this.fish.remove()); | |
foundNewLocation = true; | |
} | |
} | |
} | |
// specify Cat behavior | |
$wnd.xh.CatMovebehavior = function CatMovebehavior() {}; | |
$wnd.xh.CatMovebehavior.prototype = $wnd.Object.create($wnd.xh.FishMovebehavior.prototype); | |
//# 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> | |
<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(); | |
//# 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]; | |
me.println(gcpline); | |
for (var j = 0; j < gcpline.length; j++) { | |
switch (gcpline[j]) { | |
case "L": | |
col.xhc("LandCell"); | |
break; | |
default: | |
break; | |
} | |
col = col.next(); | |
} | |
fcol = fcol.port(2); | |
col = fcol; | |
//row = row.next(); | |
} | |
} | |
} | |
//# sourceURL=GridCellPatternbehaviorGridCellPatternbehavior.js | |
]]></GridCellPatternbehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="140" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>Ocean</title> | |
<rect id="IslandSystem/Ocean" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
<g> | |
<title>Island</title> | |
<rect id="IslandSystem/Ocean/Island" fill="#6AB06A" height="50" width="10" x="80" y="0"/> | |
</g> | |
<g> | |
<title>PlantBehaviors</title> | |
<rect id="IslandSystem/PlantBehaviors" fill="orange" height="50" width="10" x="100" y="0"/> | |
</g> | |
<g> | |
<title>FishBehaviors</title> | |
<rect id="IslandSystem/FishBehaviors" fill="orange" height="50" width="10" x="120" y="0"/> | |
</g> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment