|
<?xml version="1.0" encoding="UTF-8"?> |
|
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Thu Nov 12 2020 07:05:16 GMT-0500 (Eastern Standard Time)--> |
|
<XholonWorkbook> |
|
|
|
<Notes><![CDATA[ |
|
Xholon |
|
------ |
|
Title: Staying Alive |
|
Description: |
|
Url: http://www.primordion.com/Xholon/gwt/ |
|
InternalName: 48b6726c8a8a95bf4608b26dff199e52 |
|
Keywords: |
|
|
|
My Notes |
|
-------- |
|
November 2, 2020 |
|
|
|
See my notes from Nov 2, in the Island Games binder. |
|
|
|
|
|
References |
|
---------- |
|
|
|
(1) https://en.wikipedia.org/wiki/Fisher |
|
Fisher is an archaic term for a fisherman, revived as gender-neutral. |
|
|
|
(2) https://en.wikipedia.org/wiki/Fisherman |
|
A fisher or fisherman is someone who captures fish and other animals from a body of water, or gathers shellfish. |
|
Worldwide, there are about 38 million commercial and subsistence fishers and fish farmers. |
|
Fishers may be professional or recreational. Fishing has existed as a means of obtaining food since the Mesolithic period. |
|
|
|
]]></Notes> |
|
|
|
<markdown><![CDATA[ |
|
Staying Alive |
|
------------- |
|
|
|
This is a Xholon model called Staying Alive. |
|
|
|
### Grid |
|
|
|
The two-dimensional (2D) grid is 49 cells wide by 49 cells high (49x49). |
|
|
|
### Cells |
|
|
|
Most Cells in the grid are Ocean cells. There is also one Coast cell for each fisher. |
|
|
|
### Fish |
|
|
|
Fish move randomly through the Ocean and Coast cells. |
|
|
|
### Fishers |
|
|
|
There are two types of fishers. |
|
|
|
Subsistence fishers fish to survive. Their only goal is to stay alive. |
|
|
|
Commercial fishers fish to survive, but also to make money. They have two goals, to stay alive, and to make money. |
|
|
|
In this model, there is one commercial fisher, and eight subsistence fishers. A fisher is stationary, and never moves from the Coast cell they occupy. |
|
|
|
A fisher can catch a fish when the fish swims into the Coast cell that the fisher occupies. |
|
|
|
### Energy |
|
|
|
Each fish and fisher has an energy value. |
|
|
|
A fisher dies if their energy value reaches zero. |
|
|
|
### Outlier |
|
|
|
Write out my idea about outliers. In this model, the commercial fisher is an outlier. It catches many more fish than any subsistence fisher. |
|
This somehow connects with the idea of Exploitation. |
|
Only an outlier can be said to engage in exploitation. |
|
I've written some of this down in my various notes. |
|
also see https://gist.github.com/kenwebb/6630319996d63d003b4e5c1711380e52 |
|
|
|
My idea is that: |
|
If over time there are more fishers, there is no exploitation even if some of them die from overfishing. |
|
But the outlier commercial fisher does produce exploitation. |
|
|
|
Autopoietic vs allopoietic |
|
|
|
Subsistence fishers are unable to exploit other fishers, because they have nothing to offer them and no money to buy a boat to reach other islands. |
|
The commercial fisher has surplus money/fish and could offer employment to other fishers, and could reach them by buying a boat. |
|
|
|
ABM is especially good at handling outliers, because it deals with individuals some of which may be outliers. |
|
A statistical model has a difficult time dealing with outliers. |
|
|
|
The two types of fisher are subpopulations of an overall population. |
|
Each subpopulation may have different goals, behaviors, parameters/values. |
|
The subpopultations are continuous with each other. They overlap. |
|
Possibly they are overlapping clusters within a population. |
|
|
|
This is analogous to members of a biological species that consists of a continuous gradation of subpopulations. |
|
Where the subpopulations at the extreme geographical ends cannot breed with other. |
|
An example of this is a flower or butterfly or some such that I read about, with a habitat that stretches from Europe to east Asia. |
|
|
|
I read about or saw a video (but can't find it now) of boids flocking. |
|
It also includes a single boid flying in a straight line through the flock. To me, this is an outlier. |
|
This single outlier boid can drive/steer the direction that the entry flock moves in. |
|
It disrupts the entire flock. |
|
If this outlier boid were able to steer the entire flock into a trap, would it constitute exploitation? |
|
|
|
TODO add more from my notes |
|
|
|
### Notes |
|
miscellaneous notes |
|
|
|
The fishers are not evenly spaced in the grid. |
|
The one closest to the top, and the one closest to the bottom, are quite close to each other. |
|
The same goes for the ones closest to the right and left edges. |
|
|
|
TODO Allow all params to be optionally included as part of the URL, as was done in Universe of Fish. |
|
|
|
### Tests |
|
|
|
#### Test 1 |
|
|
|
Subsistence fishers: 9 |
|
|
|
Commercial fisher: 0 |
|
|
|
Fish: 500 Fish do not reproduce. They only die when they are caught by a fisher. |
|
The value of 500 is intended to be effectively infinite during the early part of a simulation run. |
|
Increase the initial number of fish to 1000 or whatever to derive a stable energy value for the fishers, over some initial period of time. |
|
|
|
Independent value: the number of fish |
|
|
|
Dependent value: the average/total energy of the fishers over time. It should gradually decrease and eventually reach zero. |
|
|
|
Each time step, record the number of fish, and the average/total energy of the fishers |
|
|
|
It's expected that all fishers will die of starvation (energy = 0) at around the same timestep. |
|
|
|
A fisher will only catch a fish when they are hungry. I need to define what "hungry" means, perhaps an energy level less than X. |
|
|
|
### Test 2 |
|
|
|
Same as test 1, but fish reproduce at a rate that balances the rate at which fishers catch fish. |
|
This is a stable sustainable system that should last indefinitely. |
|
|
|
#### Test 3 |
|
|
|
Same as test 2, but the centrally located fisher becomes a commercial fisher. |
|
|
|
The commercial fisher will catch a fish whenever a fish swims into that coast cell, and will eat one of these fish according to the same survival rules as in test 1 and 2. |
|
|
|
This should eventually effect the results for the subsistence fishers. |
|
|
|
Perhaps the commercial fisher has two values: energy and money |
|
When it catches a fish, it either eats the fish and increases its energy (to further its survival goal, in its role as biological organism), |
|
or it increases its money value (to further its economic goal, in its role as ???. |
|
Eating a fish to further to survival goal, is the cost of doing business (the economic goal). |
|
|
|
Is this now an economic model? |
|
|
|
#### Other Tests |
|
- 1D cyclic model 1x2401 fishers are evenly spaced, fish swim from left to right |
|
- others |
|
|
|
### Probabilistic Programming |
|
Each fish is created with a specific energy value. If a fisher eats the fish, they will increase their energy value by this amount. |
|
|
|
see http://127.0.0.1:8080/war/wb/editwb.html?app=f593df6cad526e0da7629b421916f8db&src=gist |
|
or https://gist.github.com/kenwebb/ |
|
|
|
see https://agentmodels.org/ and http://webppl.org/ and http://probmods.org/ |
|
|
|
use &jslib=webppl.min on URL line |
|
|
|
http://127.0.0.1:8080/war/Xholon.html?app=f593df6cad526e0da7629b421916f8db&src=gist&gui=clsc&jslib=webppl.min,mustache.min |
|
|
|
Which distribution should I use to represent fish sizes (energy available from eating a fish)? |
|
Smaller sizes are more common than bigger sizes. |
|
|
|
For now, use Normal distribtion (webppl Gaussian) with mean (mu) = 25.0, in range (sigma) from 15.0 to 35.0. |
|
|
|
Gaussian({mu: ..., sigma: ...}) |
|
|
|
mu: mean (real) |
|
sigma: standard deviation (real (0, Infinity)) |
|
|
|
Distribution over reals. |
|
|
|
Wikipedia entry |
|
|
|
webppl.run('sample(Gaussian({mu: 25.0, sigma: 10}))', function(s, val) {console.log(val);}); |
|
|
|
]]></markdown> |
|
|
|
<_-.XholonClass> |
|
<IslandSystem/> |
|
|
|
<!-- DO NOT SPECIFY these two Xholon classes; GridGenerator will create them |
|
<Space/> |
|
<FieldRow/> |
|
--> |
|
|
|
<!-- GridGenerator requires that these NOT have a superclass such as IslandGridCell --> |
|
<!--<IslandGridCell>--> |
|
<OceanCell/> <!-- OceanCell is the default --> |
|
<CoastCell/> |
|
<!--</IslandGridCell>--> |
|
|
|
<GridCellPattern superClass="Attribute_String"/> |
|
<GridCellPatterns/> |
|
|
|
<Animal> |
|
<Fish/> |
|
</Animal> |
|
|
|
<!-- containers for behaviors --> |
|
<FishBehaviors/> |
|
|
|
<Fisher superClass="Avatar"> <!-- see [ref 1,2] --> |
|
<SubsistFisher/> <!-- Subsistence Fisher --> |
|
<CommercFisher/> <!-- Commercial Fisher --> |
|
</Fisher> |
|
|
|
<HandleFishS superClass="Script"/> <!-- a behavior of SubsistFisher --> |
|
<HandleFishC superClass="Script"/> <!-- a behavior of CommercFisher --> |
|
|
|
<GridContentGenerator superClass="Script"/> <!-- a child of GridGenerator --> |
|
|
|
<CaptionUpdater superClass="Script"/> <!-- updates the captions every timestep --> |
|
|
|
</_-.XholonClass> |
|
|
|
<xholonClassDetails> |
|
<CoastCell implName="org.primordion.xholon.base.GridEntity"><Color>#d0c883</Color></CoastCell> <!-- #d0c883(olive) --> |
|
|
|
<Fish><Symbol>LRTriangle</Symbol><Color>SteelBlue</Color></Fish> <!-- Tuna silver,SteelBlue --> |
|
|
|
<SubsistFisher><Symbol>SmallRectangle</Symbol><Color>purple</Color></SubsistFisher> |
|
<CommercFisher><Symbol>SmallRectangle</Symbol><Color>green</Color></CommercFisher> |
|
|
|
<!-- SubsistFisher behavior energyInc 10 12 13 14 15 16 20 22 24 25 --> |
|
<HandleFishS><DefaultContent> |
|
var me, fshr, energyInitial = 200, energyInc = 25, beh = { |
|
postConfigure: function() { |
|
me = this.cnode; |
|
me.println(energyInc); |
|
fshr = me.parent().parent(); |
|
var xhcName = fshr.xhc().name(); |
|
if (!fshr["subtrees"]) { |
|
fshr.action("param subtrees true"); |
|
} |
|
fshr.energy = energyInitial; |
|
}, |
|
act: function() { |
|
var maybeFish = fshr.next(); |
|
if (maybeFish && (maybeFish.xhc().name() == "Fish") && fshr.energy < energyInitial) { |
|
this.subsist(maybeFish); |
|
} |
|
fshr.energy--; |
|
if (fshr.energy <= 0) {fshr.energy = 0; fshr.remove()} |
|
}, |
|
subsist: function(fish) { |
|
fshr.action("take " + fish.name() + ";eat " + fish.name()); |
|
fshr.energy += fish.energy; //energyInc; |
|
} |
|
} |
|
//# sourceURL=HandleFishSbehavior.js |
|
</DefaultContent></HandleFishS> |
|
|
|
<!-- CommercFisher behavior --> |
|
<HandleFishC><DefaultContent> |
|
var me, fshr, energyInitial = 200, energyInc = 25, moneyInitial = 0, moneyInc = 25, beh = { |
|
postConfigure: function() { |
|
me = this.cnode; |
|
me.println(energyInc); |
|
fshr = me.parent().parent(); |
|
var xhcName = fshr.xhc().name(); |
|
if (!fshr["subtrees"]) { |
|
fshr.action("param subtrees true"); |
|
} |
|
fshr.energy = energyInitial; |
|
fshr.money = moneyInitial; |
|
}, |
|
act: function() { |
|
var maybeFish = fshr.next(); |
|
if (maybeFish && (maybeFish.xhc().name() == "Fish")) { |
|
if (fshr.energy < energyInitial) { |
|
this.subsist(maybeFish); |
|
} |
|
else { |
|
this.commercialize(maybeFish); |
|
} |
|
$wnd.xh.svg.caption.textContent = "CommercFisher: energy " + fshr.energy.toFixed(0) + " money " + fshr.money; |
|
} |
|
fshr.energy--; |
|
if (fshr.energy <= 0) {fshr.energy = 0; fshr.remove()} |
|
}, |
|
subsist: function(fish) { |
|
fshr.action("take " + fish.name() + ";eat " + fish.name()); |
|
fshr.energy += fish.energy; //energyInc; |
|
}, |
|
commercialize: function(fish) { |
|
fshr.action("take " + fish.name() + ";unbuild " + fish.name()); |
|
fshr.money += moneyInc; |
|
} |
|
} |
|
//# sourceURL=HandleFishCbehavior.js |
|
</DefaultContent></HandleFishC> |
|
|
|
<GridContentGenerator><DefaultContent> |
|
var me, energyArr, numFish = 500, beh = { |
|
postConfigure: function() { |
|
me = this.cnode; |
|
// print a bunch of info about the model |
|
me.println("GridContentGenerator info:"); |
|
me.println(me.name()); |
|
me.println(me.params); |
|
me.println(numFish); |
|
var json = $wnd.xh.xport("Json", me.parent(), "{}", false, true); |
|
var jso = JSON.parse(json); |
|
var gg = jso.GridGenerator; |
|
me.println(gg.nameGrid); |
|
me.println(gg.rows); |
|
me.println(gg.cols); |
|
var gridNode = me.parent().xpath("../" + gg.nameGrid); |
|
me.println(gridNode.name()); |
|
|
|
if ($wnd.webppl) { |
|
var str = `var funk = function() { return sample(Gaussian({mu: 25.0, sigma: 5.0})) }\nrepeat(${numFish}, funk)`; |
|
$wnd.webppl.run(str, function(s, val) { |
|
energyArr = val; |
|
//console.log(energyArr); // val is a JS Array |
|
}); |
|
} |
|
else { |
|
energyArr = []; |
|
energyArr.length = numFish; |
|
energyArr.fill(25.0); |
|
} |
|
|
|
}, |
|
act: function() { |
|
var cellArr = $wnd.xh.cellArr; |
|
if (cellArr) { |
|
var cellArrLen = cellArr.length; |
|
me.println("Number of grid cells: " + cellArrLen); |
|
var fish = me.first(); |
|
fish.color("red"); // mark one fish so it's easy to follow by looking at the grid |
|
me.println("Name of first fish: " + fish.name()); // OK |
|
var numFish = me.numChildren(); |
|
me.println("Number of fish: " + numFish); |
|
var energyIx = 0; |
|
while (fish) { |
|
fish.energy = energyArr[energyIx++]; |
|
//console.log(fish); |
|
var nextFish = fish.next(); |
|
cellArr[Math.floor(Math.random()*cellArrLen)].append(fish.remove()); |
|
fish = nextFish; |
|
} |
|
me.parent().remove(); |
|
} |
|
} |
|
} |
|
//# sourceURL=GridContentGenerator.js |
|
</DefaultContent></GridContentGenerator> |
|
|
|
<CaptionUpdater><DefaultContent> |
|
var me, beh = { |
|
postConfigure: function() { |
|
me = this.cnode; |
|
me.println(me.name()); |
|
|
|
}, |
|
act: function() { |
|
const sfisherArr = $wnd.xh.sfisherArr; |
|
if (sfisherArr) { |
|
const energyArr = sfisherArr.map(fshr => fshr.energy.toFixed(0)); |
|
const reducer = (accumulator, currentValue) => Number(accumulator) + Number(currentValue); |
|
$wnd.xh.svg2.caption.textContent = "SubsistFisher: energy " + energyArr + " mean " + (energyArr.reduce(reducer, 0) / energyArr.length).toFixed(0); |
|
} |
|
} |
|
} |
|
//# sourceURL=CaptionUpdater.js |
|
</DefaultContent></CaptionUpdater> |
|
|
|
</xholonClassDetails> |
|
|
|
<IslandSystem> |
|
<!-- entire grid; rows and cols must be same as const ROWS and const COLS in Behaviors --> |
|
<GridGenerator |
|
rows="49" |
|
cols="49" |
|
gridType="Gvt" |
|
names="Space,FieldRow,OceanCell" |
|
columnColor="171c8f" |
|
gridViewerParams="IslandSystem/Space,8,Island Viewer,true" |
|
shouldBuildXhc="true" |
|
shouldBuildCsh="true" |
|
cellsCanSupplyOwnColor="true" |
|
shouldRemoveSelf="false" |
|
> |
|
<GridContentGenerator params='{one="ONE", two="DEUX"}'> |
|
<Fish multiplicity="500"/> |
|
</GridContentGenerator> |
|
</GridGenerator> |
|
|
|
<!-- C = CoastCell+SubsistFisher K = CoastCell+CommercFisher . = OceanCell --> |
|
<GridCellPatterns> |
|
|
|
<GridCellPattern xpos="0" ypos="0" ><![CDATA[ |
|
................................................. |
|
........................C........................ |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
............C.......................C............ |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
.C......................K......................C. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
............C.......................C............ |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
................................................. |
|
........................C........................ |
|
................................................. |
|
]]></GridCellPattern> |
|
|
|
</GridCellPatterns> |
|
|
|
<FishBehaviors> |
|
<!--<script> |
|
var me, fishbehs, sbcount = 0, ycount = 0, beh = { |
|
postConfigure: function() {me = this.cnode; fishbehs = me.parent();}, |
|
act: function() { |
|
//console.log(fishbehs.numChildren()); |
|
var node = me.next(); |
|
//console.log(node.c.fish.color()); |
|
while (node) { |
|
//console.log(node.c.fish.color()); |
|
//node.c.fish.color() === "yellow" ? ycount++ : sbcount++; |
|
console.log(node.c.fish.color() || node.c.fish.xhc().color()); |
|
node = node.next() |
|
} |
|
me.println(ycount + " " + sbcount + " " + fishbehs.numChildren()); |
|
ycount = 0; |
|
sbcount = 0; |
|
} |
|
} |
|
</script>--> |
|
</FishBehaviors> |
|
|
|
<!-- see Xml2Xholon - DefaultContent only works if I include RoomModel somewhere before I need to use DefaultContent --> |
|
<RoomModel/> |
|
|
|
<CaptionUpdater/> |
|
|
|
</IslandSystem> |
|
|
|
<IslandSystembehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ |
|
const ROWS = 49; // same as value in GridGenerator |
|
const COLS = 49; // same as value in GridGenerator |
|
const GRID_CELL_SIZE = 8; // same as value in GridGenerator gridViewerParams |
|
const FISH_SHOULD_REPRODUCE = true; |
|
|
|
//$wnd.xh.seed(234); // 234 |
|
$wnd.xh.param("TimeStepInterval","100"); |
|
$wnd.xh.param("MaxProcessLoops","1000"); |
|
$wnd.xh.param("AppM","true"); |
|
|
|
if ($wnd.xh.html["selectTab"]) { |
|
$wnd.xh.html.selectTab(0); // display contents of the "out" tab |
|
} |
|
$wnd.xh.css.style("#xhchart {font-family: monospace; font-size: 13.3333px; font-weight: 400;}"); |
|
|
|
// commands for built-in system Avatar; can use this Avatar as an observer and controller |
|
var akm = `{ |
|
"SHIFT":"true", |
|
"NOSCROLL":"true", |
|
"UP":"go port0;", |
|
"DOWN":"go port2;", |
|
"LEFT":"prev;", |
|
"RIGHT":"next;", |
|
"p":"pause;", |
|
"r":"start;", |
|
"s":"step;", |
|
" ":"step;", |
|
"W":"who;where;look;", |
|
"a":"appear;", |
|
"v":"vanish;" |
|
}`; |
|
$wnd.xh.avatarKeyMap(akm); |
|
var ava = $wnd.xh.avatar(); |
|
ava.action('param meteor false;'); |
|
ava.action('step'); |
|
ava.action('enter;enter xpath(Space/*/*);'); |
|
ava.action('who;where;'); |
|
|
|
// fix problem where if I click within the canvas, then keystrokes don't get to the Avatar (see Island B3 workbook, rev 8) |
|
var canvas = $doc.querySelector("div#xhcanvas > canvas"); |
|
canvas.onmousedown = function(event) {event.preventDefault();}; |
|
// prevent display of Xholon context menu (right-click) |
|
//canvas.oncontextmenu = function(event) {event.preventDefault();}; |
|
// disable context menu for the entire screen |
|
$doc.oncontextmenu = function(event) {event.preventDefault();}; |
|
|
|
// SVG caption |
|
$wnd.xh.svg = {}; |
|
$wnd.xh.svg.caption = $doc.createElement("p"); |
|
$wnd.xh.svg.caption.textContent = $wnd.xh.param("ModelName"); |
|
|
|
// another SVG caption |
|
$wnd.xh.svg2 = {}; |
|
$wnd.xh.svg2.caption = $doc.createElement("p"); |
|
$wnd.xh.svg2.caption.textContent = "InheritanceHierarchy > XholonClass > object"; |
|
|
|
var div = $doc.querySelector("#xhchart"); |
|
|
|
// create a new div for this animation |
|
var one = $doc.createElement("div"); |
|
one.setAttribute("id", "one"); |
|
div.appendChild(one); |
|
|
|
// create a second new div for this animation |
|
var two = $doc.createElement("div"); |
|
two.setAttribute("id", "two"); |
|
div.appendChild(two); |
|
|
|
one.appendChild($wnd.xh.svg.caption); |
|
two.appendChild($wnd.xh.svg2.caption); |
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
// 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() { |
|
/*if (this.fish.color() == "yellow") { |
|
console.log(" YELLOW"); |
|
} |
|
else { |
|
console.log(" STEELBLUE"); |
|
}*/ |
|
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 == "OceanCell") || (pname == "CoastCell")) { |
|
// move randomly in the grid |
|
this.move(); |
|
} |
|
}; |
|
$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.append(this.fish.remove()); |
|
foundNewLocation = true; |
|
} |
|
} |
|
}; |
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
// specify Fish Reproduce behavior |
|
$wnd.xh.FishReproducebehavior = function FishReproducebehavior() {} |
|
if(FISH_SHOULD_REPRODUCE) { |
|
$wnd.xh.FishReproducebehavior.prototype.postConfigure = function() { |
|
this.fish = this.cnode.parent(); |
|
this.fish.xpath("ancestor::IslandSystem/FishBehaviors").append(this.cnode.remove()); |
|
}; |
|
$wnd.xh.FishReproducebehavior.prototype.act = function() { |
|
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 == "OceanCell") || (pname == "CoastCell")) { |
|
this.reproduce(); |
|
} |
|
}; |
|
$wnd.xh.FishReproducebehavior.prototype.reproduce = function() { |
|
if (Math.random() > 0.999) { |
|
const cellArr = $wnd.xh.cellArr; |
|
if (cellArr) { |
|
this.fish.println("REPRODUCING ..."); |
|
const fish = `<Fish energy="25.0"> |
|
<Fishbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"> |
|
var beh = new $wnd.xh.FishMovebehavior(); |
|
</Fishbehavior> |
|
</Fish>`; |
|
const cellArrLen = cellArr.length; |
|
const cellInstance = cellArr[Math.floor(Math.random()*cellArrLen)]; |
|
cellInstance.append(fish); |
|
const newFish = cellInstance.last(); |
|
newFish.energy = Number(newFish.energy); |
|
//console.log(newFish); |
|
} |
|
} |
|
}; |
|
} |
|
|
|
//# sourceURL=IslandSystembehavior.js |
|
]]></IslandSystembehavior> |
|
|
|
<Fishbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ |
|
var beh = new $wnd.xh.FishMovebehavior(); |
|
//# sourceURL=FishMovebehavior.js |
|
]]></Fishbehavior> |
|
|
|
<Fishbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ |
|
var beh = new $wnd.xh.FishReproducebehavior(); |
|
//# sourceURL=FishReproducebehavior.js |
|
]]></Fishbehavior> |
|
|
|
<GridCellPatternbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"> |
|
<![CDATA[ |
|
const colorArr = ["Subsist", "Commerc"]; |
|
const akmArr = [ |
|
`{ |
|
"SHIFT":"false", |
|
"NOSCROLL":"true", |
|
"w":"who;where;look all;inventory;" |
|
}` |
|
]; |
|
//const NUM_FISH = 100; // number of fish of each color to create |
|
|
|
const CATCH_FISH_S = '<HandleFishS></HandleFishS>'; |
|
const CATCH_FISH_C = '<HandleFishC></HandleFishC>'; |
|
|
|
var me, colorArrIx, beh = { |
|
postConfigure: function() { |
|
me = this.cnode.parent(); // GridCellPattern node |
|
var pNode = me.parent(); // GridCellPatterns node |
|
colorArrIx = 0; |
|
var gcp = me; // GridCellPattern node |
|
var gcpstr = gcp.text().trim(); |
|
var gcparr = gcpstr.split("\n"); |
|
var row = me.xpath("../../Space/FieldRow[" + gcp.ypos + "]"); |
|
var fcol = row.xpath("OceanCell[" + gcp.xpos + "]"); |
|
var col = fcol; |
|
var cellArr = []; // cache all cells |
|
var sfisherArr = []; // cache all Subsistence Fishers |
|
for (var i = 0; i < gcparr.length; i++) { |
|
var gcpline = gcparr[i].trim(); |
|
for (var j = 0; j < gcpline.length; j++) { |
|
switch (gcpline[j]) { |
|
case "C": |
|
col.xhc("CoastCell"); |
|
cellArr.push(col); |
|
// A v a t a r |
|
var avastr = '<' + "Subsist" + 'Fisher shouldReceiveKeyEvents="false">' |
|
+ '<Attribute_String roleName="script">who;where</Attribute_String>' |
|
//+ '<Attribute_String roleName="akm">' |
|
//+ akmArr[colorArrIx] |
|
//+ '</Attribute_String>' |
|
+ '<BehaviorsST>' |
|
+ CATCH_FISH_S |
|
+ '</BehaviorsST>' |
|
+ '</' + "Subsist" + 'Fisher>' |
|
+ ''; |
|
col.append(avastr); |
|
sfisherArr.push(col.last()); |
|
break; |
|
case "K": // CoastCell + Avatar/CommercFisher |
|
col.xhc("CoastCell"); |
|
cellArr.push(col); |
|
// A v a t a r |
|
var avastr = '<' + "Commerc" + 'Fisher shouldReceiveKeyEvents="true">' |
|
+ '<Attribute_String roleName="script">who;where</Attribute_String>' |
|
+ '<Attribute_String roleName="akm">' |
|
+ akmArr[colorArrIx] |
|
+ '</Attribute_String>' |
|
+ '<BehaviorsST>' |
|
+ CATCH_FISH_C |
|
+ '</BehaviorsST>' |
|
+ '</' + "Commerc" + 'Fisher>' |
|
+ ''; |
|
col.append(avastr); |
|
break; |
|
case ".": |
|
cellArr.push(col); |
|
break; |
|
default: // "." |
|
break; |
|
} |
|
col = col.next(); |
|
} |
|
fcol = fcol.port(2); |
|
col = fcol; |
|
} |
|
$wnd.xh.cellArr = cellArr; |
|
$wnd.xh.sfisherArr = sfisherArr; |
|
} |
|
} |
|
//# sourceURL=GridCellPatternbehavior.js |
|
]]></GridCellPatternbehavior> |
|
|
|
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, |
|
<svg width="100" height="10" xmlns="http://www.w3.org/2000/svg"> |
|
<g> |
|
<title>Space</title> |
|
<rect id="IslandSystem/Space" fill="#98FB98" height="10" width="10" x="0" y="0"/> |
|
<g> |
|
<title>Cell</title> |
|
<rect id="IslandSystem/Space/*/*" fill="#6AB06A" height="10" width="10" x="20" y="0"/> |
|
</g> |
|
<g> |
|
<title>FishBehaviors</title> |
|
<rect id="IslandSystem/FishBehaviors" fill="pink" height="10" width="10" x="40" y="0"/> |
|
</g> |
|
</g> |
|
</svg> |
|
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> |
|
|
|
</XholonWorkbook> |