DOCUMENTATION TUTORIALS DOWNLOAD NEWS CONTRIBUTE

Variables and Attributes

Variables and attributes represent named data that can be used in an expression. They can be accessed depending on their scope:

Table of contents

Direct Access

When an agent wants to use either one of the variables declared locally, one of the attributes declared in its species (or parent species), one of the attributes declared in the macro-species of its species, it can directly invoke its name and the compiler will do the rest (i.e. finding the variable or attribute in the right scope). For instance, we can have a look at the following example:

species animal {
   float energy <- 1000 min: 0 max: 2000 update: energy - 0.001;
   int age_in_years <- 1 update: age_in_years + int (time / 365);
   
   action eat (float amount <- 0) {
       float gain <- amount / age_in_years;
       energy <- energy + gain;
   }

   reflex feed {
      int food_found <- rnd(100);
      do eat (amount: food_found); 
   }

}

Remote Access

When an expression needs to get access to the attribute of an agent which does not belong to its scope of execution, a special notation (similar to that used in Java) has to be used:

remote_agent.variable

where remote_agent can be the name of an agent, an expression returning an agent, self, myself or each. For instance, if we modify the previous species by giving its agents the possibility to feed another agent found in its neighbourhood, the result would be:

species animal {
   float energy <- 1000 min: 0 max: 2000 update: energy - 0.001;
   int age_in_years <- 1 update: age_in_years + int (time / 365);
   action eat (float amount <- 0.0) {
       float gain <- amount / age_in_years;
       energy <- energy + gain;
   }
   action feed (animal target){
       if (agent_to_feed != nil) and (agent_to_feed.energy < energy { // verifies that the agent exists and that it need to be fed
            ask agent_to_feed {
                do eat amount: myself.energy / 10; // asks the agent to eat 10% of our own energy
            }
            energy <- energy - (energy / 10); // reduces the energy by 10%
       }
   }
   reflex {
       animal candidates <- agents_overlapping (10 around agent.shape); gathers all the neighbours
       agent_to_feed value: candidates with_min_of (each.energy); //grabs one agent with the lowest energy 
       do feed target: agent_to_feed; // tries to feed it
   }
}

In this example, agent_to_feed.energy, myself.energy and each.energy show different remote accesses to the attribute energy. The dotted notation used here can be employed in assignments as well. For instance, an action allowing two agents to exchange their energy could be defined as:

action random_exchange {//exchanges our energy with that of the closest agent
     animal one_agent <- agent_closest_to (self)/>
     float temp  <-one_agent.energy; // temporary storage of the agent's energy
     one_agent.energy <- energy; // assignment of the agent's energy with our energy
     energy <- temp;
}