Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active November 12, 2020 12:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/48b6726c8a8a95bf4608b26dff199e52 to your computer and use it in GitHub Desktop.
Save kenwebb/48b6726c8a8a95bf4608b26dff199e52 to your computer and use it in GitHub Desktop.
Staying Alive

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);});

<?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 &amp;&amp; (maybeFish.xhc().name() == "Fish") &amp;&amp; fshr.energy &lt; energyInitial) {
this.subsist(maybeFish);
}
fshr.energy--;
if (fshr.energy &lt;= 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 &amp;&amp; (maybeFish.xhc().name() == "Fish")) {
if (fshr.energy &lt; 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 &lt;= 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment