Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active June 2, 2018 12:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/c8e4d796b9d76021d677a1d712ecadae to your computer and use it in GitHub Desktop.
Save kenwebb/c8e4d796b9d76021d677a1d712ecadae to your computer and use it in GitHub Desktop.
Island 1
<?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