/**
* Firefighters
* Author: Mathieu Bourgais
* Description: A simple model to show how the BDI architectures and its tools work (perceive, rule, etc). It's the model of a helicopter that fights fires.
* the Chopper agent has a general desire to patrol. As it is the only thing he wants at the beginning, it is its initial intention (what it is doing).
* To patrol, it wanders around (its plan to patrol). When it perceives a fire, it stores this information (it has a new belief about the existence of this fire),
* and it has a new desire (it wants the fire to be extinct). When it sees a fire, the Patrol intention is put on hold and a new intention is selected (to put out the fire).
* To achieve this intention, the plan has two steps, i.e. two new (sub)desires: go to the fire and put water on the fire. And so on.
* Tags: simple_bdi, perception, rule, plan, predicate
*/
model Firefighters
global {
int displatTextSize <-4;
//We define the predicates that will be used later.
predicate patrol_desire <- new_predicate("patrol");
predicate water_predicate <- new_predicate("has water",true);
predicate no_water_predicate <- new_predicate("has water", false) ;
string fireLocation <- "fireLocation";
init {
create fireArea number:20;
create waterArea number:1;
create firefighter number: 2;
}
reflex stop when: length(fireArea) = 0 {
do pause;
}
}
//give the simple_bdi architecture to the firefighter agents
species firefighter skills: [moving] control: simple_bdi{
//Here are the variables used by a helicopter.
rgb color <- rnd_color(150);
float waterValue;
grille maCellule <- one_of(grille);
//Definition of the variables featured in the BDI architecture.
float plan_persistence <- 1.0;
float intention_persistence <- 1.0;
bool probabilistic_choice <- false;
//Initialisation of the agent. At the begining, the agent just has the desire to patrol.
init {
waterValue <-2.0;
location<-maCellule.location;
do add_desire(patrol_desire );
}
//This perceive is used to update the beliefs concerning the intern variable of the agent (the amount of water it has).
perceive target:self {
if(waterValue>0){
do add_belief(water_predicate);
do remove_belief(no_water_predicate);
}
if(waterValue<=0){
do add_belief(no_water_predicate);
do remove_belief(water_predicate);
}
}
//The helicopter perceive the fires at a certain distance. It just record the location of the fire it obsrves. When it sees a fire, it stops it's intention of patroling.
perceive target:fireArea in: 15{
focus id:"fireLocation" var:location strength:10.0;
ask myself{
do remove_intention(patrol_desire, true);
}
}
//The rules are used to create a desire from a belief. We can specify the priority of the desire with a statement priority.
rule belief: new_predicate(fireLocation) new_desire: get_predicate(get_belief_with_name(fireLocation));
rule belief: no_water_predicate new_desire: water_predicate strength: 10.0;
//The plan to do when the intention is to patrol.
plan patrolling intention:patrol_desire{
do wander amplitude: 30.0 speed: 2.0;
}
//The plan that is executed when the agent got the intention of extinguish a fire.
plan stopFire intention: new_predicate(fireLocation) priority:5{
point target_fire <- point(get_predicate(get_current_intention()).values["location_value"] );
if(waterValue>0){
if (self distance_to target_fire <= 1) {
fireArea current_fire <- fireArea first_with (each.location = target_fire);
if (current_fire != nil) {
waterValue <- waterValue - 1.0;
current_fire.size <- current_fire.size - 1;
if ( current_fire.size <= 0) {
ask current_fire {do die;}
do remove_belief(get_predicate(get_current_intention()));
do remove_intention(get_predicate(get_current_intention()), true);
do add_desire(patrol_desire,1.0);
}
} else {
do remove_belief(get_predicate(get_current_intention()));
do remove_intention(get_predicate(get_current_intention()), true);
do add_desire(patrol_desire,1.0);
}
} else {
do goto(target: target_fire);
}
} else {
do add_subintention(get_current_intention(),water_predicate,true);
do current_intention_on_hold();
}
}
//The plan to take water when the agent get the desire of water.
plan gotoTakeWater intention: water_predicate priority:2 {
waterArea wa <- first(waterArea);
list voisins <- (grille(location) neighbors_at (1)) + grille(location);
path cheminSuivi <- goto(wa);
if (self distance_to wa <= 1) {
waterValue <- waterValue + 2.0;
}
}
aspect base {
draw triangle(2) color:color rotate: 90 + heading;
draw circle(15) color: color ;
}
aspect bdi {
draw triangle(2) color:color rotate: 90 + heading;
draw circle(15) color: color wireframe: true;
draw ("B:" + length(belief_base) + ":" + belief_base) color:#black size:displatTextSize;
draw ("D:" + length(desire_base) + ":" + desire_base) color:#black size:displatTextSize at:{location.x,location.y+displatTextSize};
draw ("I:" + length(intention_base) + ":" + intention_base) color:#black size:displatTextSize at:{location.x,location.y+2*displatTextSize};
draw ("curIntention:" + get_current_intention()) color:#black size:displatTextSize at:{location.x,location.y+3*displatTextSize};
}
}
species fireArea{
float size <-1.0;
init{
grille place <- one_of(grille);
location <- place.location;
}
aspect base {
draw file("../includes/Fire.png") size: 5;
}
}
species waterArea{
init {
grille place <- one_of(grille);
location <- place.location;
}
aspect base {
draw square(5) color: #blue border: #black;
}
}
grid grille width: 25 height: 25 neighbors:4 {
rgb color <- #green;
}
experiment fight_fire type: gui {
float minimum_cycle_duration <- 0.05;
output {
display view1 {
grid grille border: #darkgreen;
species fireArea aspect:base;
species waterArea aspect:base;
species firefighter aspect: bdi;
}
}
}