Global - theRAPTLab/gsgo GitHub Wiki
See !110, !181
[[TOC]]
Global properties are maintained by a global agent. The global agent is just another GAgent and has all the capabilities of the GAgent.
There are two ways to access global properties:
-
Via the
global
context -
Via global prop methods
global
context is by far the easier method. (Global prop methods are a historical artifact: they were added prior to the global
context approach and still work.)
!181
A global
agent context is passed to all scripts. This means that any script can reference global properties directly by using global
.
For example, let's say you've defined a global property sparkCounter
, in a Moth script you can now do this:
prop global.sparkCounter add 1
NOTE for Population methods lke agentsForEach
that pass agent context, global
is still available, e.g. this works:
// ROUND INIT SCRIPT
// Global Prop
addProp roundCounter
// Round Init Processing
featCall Population agentsForEach TreeTrunk [[
// 'global' here would refer to GlobalAgent, not TreeTrunk
ifExpr {{ global.getProp('roundCounter').value > 1 }} [[ ... ]]
]]
(Global prop methods are a historical artifact: they were added prior to the global
context approach and still work. But the recommended method is to use the `global context' method described above.)
In order to plot properties that span agents, e.g. summative properties like "number of light moths", we've added the ability to add and track properties for a Global Agent.
This is still a very rough early take as we figure out how the Global Agent should and should not be used. Expect this to change.
Adds a GVar property to the global agent.
featCall Global addGlobalProp <propertyName> <GVar Type> <value>
where <propertyName>
is the name of the property, e.g. "darkMoths", <GVar Type>
is Number
||String
||Boolean
, and <value>
is the initial value to set the property to.
Access the GVar methods of the global property.
featCall Global globalProp <propertyName> <GVar Method> <...params>
where <propertyName>
is the name of the property, e.g. "darkMoths", <GVar Method>
is a method such as value
or setTo
or add
etc, and <...params>
are any parameters the method requires.
featCall Global globalProp darkMoths add 1
The roundTime
property reflects the current Round timer counter. e.g. if time elapsed in round is 5 seconds, then roundTimer
= 5.
- During sim-rounds'
StageInit
, aroundTime
property is added to the global agent. - At
StartRoundTimer
, the globalroundTime
property is set to 0. - With each tick, the
roundTime
property is updated to match theTIMER_COUNTER
.
Since roundTime
is a property of the global agent, any agent can access it by adding the Global
feature. Usually we use this in the context of an expression, e.g.:
ifExpr {{ agent.callFeatMethod('Global', 'getGlobalProp', 'roundTime').value > 5 }} [[
// do something
]]
See !165
The key to using Global Properties is figuring out where to define them.
In this example, we define the global properties with the reporter instance "Light Moths" line graph agent, but update the property value whenever a new moth is triggered.
# BLUEPRINT Reporter
# PROGRAM DEFINE
useFeature Global
// note we do not define the global property here
We define the global property in the instance initScript. This way it is created by the instance.
(We could define it in the # BLUEPRINT Reporter
script, but this makes the connection between the global property and the instance clearer.
// Light Moths Instance Init Script
{
id: 1402,
name: 'Light Moths',
blueprint: 'Reporter',
initScript: `
featCall Global addGlobalProp lightMoths Number 0
featCall AgentWidgets bindGraphToGlobalProp lightMoths 30
`
}
So the reporter should now display line graph updates whenever the global property lightMoths
changes.
We want to change lightMoths
count when a new Moth is spawned. So this code goes into the Moths
script:
# BLUEPRINT Moth
# PROGRAM UPDATE
when Moth centerTouches TreeTrunk [[
every 1 [[
ifExpr {{ agent.getProp('energyLevel').value > 90 }} [[
// SPAWN!
featCall Population spawnChild [[
// new spawn init script (not current agent)
// spawn randomly darker
featProp Costume colorValue subRnd 0.5
// add point to global graphs
ifExpr {{ agent.prop.Costume.colorValue.value < 0.5 }} [[
// add a point here so the graph shows a new point with no change in value
// this is also needed if we have a `darkMoths` graph that we want to synchronize with
featCall Global globalProp lightMoths add 0
]] [[
featCall Global globalProp lightMoths add 1
]]
]]
]]
]]
]]
-
Be careful about where and when you define global properties. It is easy to inadvertently redefine the same property (e.g. if you define a particular global property whenever you spawn a new agent, the duplicate definitions will trigger an error.
-
Be careful about where and when you update global properties. It is easy to try to set a property before it has been defined.
We probably need to rewrite Global Properties better address these situations. Perhaps it needs to be explicitly defined with its own script as a root agent.