package iamrescue.agent.ambulanceteam; import iamrescue.agent.AbstractIAMAgent; import iamrescue.agent.ambulanceteam.ambulancetools.AllocationMessage; import iamrescue.agent.ambulanceteam.ambulancetools.AllocationHandler; import iamrescue.agent.ambulanceteam.ambulancetools.RScheduler; import iamrescue.agent.ambulanceteam.ambulancetools.Task; import iamrescue.agent.ambulanceteam.ambulancetools.RScheduler.RescueTask; import iamrescue.execution.command.DigOutCommand; import iamrescue.execution.command.IPath; import iamrescue.execution.command.LoadCommand; import iamrescue.execution.command.MoveCommand; import iamrescue.execution.command.RestCommand; import iamrescue.execution.command.UnloadCommand; import iamrescue.routing.IRoutingModule; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; import rescuecore2.standard.entities.AmbulanceTeam; import rescuecore2.standard.entities.Area; import rescuecore2.standard.entities.Building; import rescuecore2.standard.entities.Civilian; import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.Refuge; import rescuecore2.standard.entities.Road; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.worldmodel.ChangeSet; import rescuecore2.worldmodel.EntityID; public class IAMAmbulanceTeam extends AbstractIAMAgent<StandardEntity> { private static int LONG_TRAVEL_TIME_IGNORE = 15; private static int IGNORE_UNTIL_TIME_STEP = 150; /*private static int TIME_STEP_THRESHOLD = 3; private static double SEARCH_PROBABILITY = 0.05; private static int LONG_TIME_STEP_THRESHOLD = 20; private static double LONG_SEARCH_PROBABILITY = 0.2; private static int LONG_SEARCH_STEPS = 10; */ //private int @Override protected List<StandardEntityURN> getAgentTypes() { // TODO Auto-generated method stub List<StandardEntityURN> list = new ArrayList<StandardEntityURN>(); list.add(StandardEntityURN.AMBULANCE_TEAM); return list; } public StandardEntityURN getAgentType() { return StandardEntityURN.AMBULANCE_TEAM; } private static final Logger LOGGER = Logger.getLogger(IAMAmbulanceTeam.class); /** * This implementation of an ambulance team uses RScheduler to decide the next civilian to rescue. * If it doesn't know anything then it doesn't move. */ int [] d=new int[300], r=new int[300], ir=new int[300], f=new int[300]; int ind=0; /** * The list of ids in my team */ private AmbulanceTeam[] team; /** * determines if the agent is buried */ //private boolean wasBuried; /** * determines if the agent is stuck */ //private boolean iamStuck; /** * determines if the agent has got a loaded victim */ private boolean loadedVictim; /** * the victim to save in this time step */ protected Human target; /** * the scheduler used to compute which victim to go to. */ private RScheduler scheduler; /** * the list of well-known targets */ private ArrayList<StandardEntity> targets; /** * */ private int myIndex; private int myTeamSize; private IRoutingModule pathPlanner; private int timeStep; private IPath path; private Collection<EntityID> allRefuges; private boolean teamSetUp = false; // ---------------methods-------------------// /** * Construct a new AladdinAmbulanceTeam */ public IAMAmbulanceTeam() { // Identify the agent type super(); // the list of well-know targets targets = new ArrayList<StandardEntity>(); } /** * Get a reference the the AmbulanceTeam controlled by this agent * @return The AmbulanceTeam controlled by this agent */ protected StandardEntity me() { // Identify the agent return (StandardEntity) getWorldModel().getEntity(this.getID()); } /** * Returns the list of targets. * @return the list of targets. */ public ArrayList<StandardEntity> getTargets() {return targets;} /** * Returns the scheduler used to compute which victim to go to. * @return the scheduler. */ public RScheduler scheduler() {return scheduler;} /** * Initialise the agent * @param knowledge - The knowledge. * @param self - The agent itself. */ public void initialiseAmbulance() { //super.initialise(); pathPlanner = this.getRoutingModule(); myTeamSize=getWorldModel().getEntitiesOfType(StandardEntityURN.AMBULANCE_TEAM).size(); if(LOGGER.isTraceEnabled()) LOGGER.trace("Ambulance Version 2.01"); // loaded a victim? loadedVictim = false; //iamStuck = false; // the team of Ambulances scheduler = new RScheduler(new ArrayList<RescueTask>(), getWorldModel(),getWorldModel().getEntitiesOfType(StandardEntityURN.BUILDING).toArray(new Building[0]), pathPlanner, timeStep,getSpeedInfo(),this,getTimer()); if ( LOGGER.isTraceEnabled() ) LOGGER.trace(" - initialise(): myTeamSize="+myTeamSize); Collection<StandardEntity> refs = getWorldModel().getEntitiesOfType(StandardEntityURN.REFUGE); Iterator<StandardEntity> it = refs.iterator(); allRefuges = new ArrayList<EntityID>(); while (it.hasNext()){ StandardEntity temp = (StandardEntity)it.next(); allRefuges.add(temp.getID()); } } /** * Sets the index and team size of this agent. * @param team The agent team. */ private void setMyIndex(AmbulanceTeam[] team) { int[] ids = new int[team.length]; for (int i=0;i<team.length;i++) { ids[i]=team[i].getID().getValue(); } Arrays.sort(ids); for(int i=0;i<team.length;i++){ team[i] = (AmbulanceTeam) getWorldModel().getEntity(new EntityID(ids[i])); } myIndex = Arrays.binarySearch(ids,this.getID().getValue()); myTeamSize = team.length; } /** * Main method - it is executed in each time step */ public void think(int time, ChangeSet changed) { AbstractIAMAgent.stopIfInterrupted(); if(!teamSetUp){ team = getWorldModel().getEntitiesOfType(StandardEntityURN.AMBULANCE_TEAM).toArray(new AmbulanceTeam[0]); setMyIndex(team); scheduler.setmyIndex(myIndex); scheduler.setTeam(team); teamSetUp=true; if(LOGGER.isTraceEnabled()) printSharedID(); } boolean takenAction = false; timeStep = time; if(LOGGER.isTraceEnabled()) LOGGER.trace(" - entering act function"); // issues a rescue message, if it is buried if (((Human)me()).getBuriedness()>0) { if(LOGGER.isTraceEnabled()) LOGGER.trace(" - buried: sending rescue message"); sendRest(timeStep); return; } // moves to closest refuge, if it is damaged if (((Human)me()).getDamage()>0) { if(allRefuges.size()>0){ moveToClosestRefuge(); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - damaged: moving to regufe"); return; } } Human nextTarget = null; Collection<StandardEntity> all_humans = getWorldModel().getEntitiesOfType(StandardEntityURN.CIVILIAN, StandardEntityURN.AMBULANCE_TEAM,StandardEntityURN.FIRE_BRIGADE,StandardEntityURN.POLICE_FORCE); ArrayList<Task> vics = getVictims(all_humans); boolean availableTask=false; // if(vics.size()>0){ availableTask=scheduler.chooseStrategy(vics, timeStep); //chooses next victims in the ordered set of all victims /* } else { all_humans = getWorldModel().getEntitiesOfType(StandardEntityURN.CIVILIAN); vics = getVictims(all_humans); availableTask=scheduler.chooseStrategy(vics, timeStep); }*/ AbstractIAMAgent.stopIfInterrupted(); if(availableTask) { //int[] nextTasksID = scheduler.encodeStrategyToSend(); //pack informations //this.getCommunicationModule().enqueueRadioMessageToOwnTeam(new AllocationMessage(nextTasksID,time)); //chose next task nextTarget= scheduler.chooseNextVictim(); } else if(LOGGER.isTraceEnabled()) { LOGGER.trace(" - next strategy's not available - scheduler cannot find any target"); } if(!all_humans.contains(target)){ //summat funny target=null; } if(target!=null){ if(LOGGER.isTraceEnabled()) LOGGER.trace(" - in non null target "); takenAction = makeAction(vics);//execute the current target AbstractIAMAgent.stopIfInterrupted(); if(!takenAction){ //need to do some searching if(LOGGER.isTraceEnabled()) LOGGER.trace(" - moving to search building "); target=null; AbstractIAMAgent.stopIfInterrupted(); this.doDefaultSearch(); } } else { target = nextTarget;//set target for the next time step if(nextTarget!=null){ takenAction = makeAction(vics);//execute the next task in this time step AbstractIAMAgent.stopIfInterrupted(); } else { //need to do some searching target=null; if(LOGGER.isTraceEnabled()) LOGGER.trace(" - moving to search building "); AbstractIAMAgent.stopIfInterrupted(); this.doDefaultSearch(); } } if(LOGGER.isTraceEnabled()) LOGGER.trace(" - finished thinking"); return; } private void printSharedID() { LOGGER.trace(" - Shared Allocation for Agent is " + myIndex); for(int i=0; i<team.length; i++){ LOGGER.trace(" - allocation: " + team[i].getID().getValue()); } } /** * Computes the list of civilians which are buried and need to be rescued * @return sorted list of victims according to their deadline */ @SuppressWarnings("unchecked") public ArrayList<Task> getVictims(Collection<StandardEntity> all_civilians) { ArrayList<Task> civsWithPaths = new ArrayList<Task>(); if (!all_civilians.isEmpty()) { Human civilian; StandardEntity civilianLocation; int howfiery = 0; // remove those that are not buried for (Iterator civ_iterator = all_civilians.iterator();civ_iterator.hasNext();) { civilian = (Human) civ_iterator.next(); if(civilian.getID().getValue()==getID().getValue()){ civ_iterator.remove(); continue; } if(civilian.isPositionDefined()){ if(LOGGER.isTraceEnabled()) LOGGER.trace(" - checking civilians " + civilian.getID() + " " + civilian.getPosition().getValue()); civilianLocation= getWorldModel().getEntity(civilian.getPosition()); if (civilianLocation instanceof Building) { if(((Building)civilianLocation).isFierynessDefined()){ howfiery = ((Building)civilianLocation).getFieryness(); if (howfiery>0 && howfiery <= 3) { civ_iterator.remove(); continue; } } /*else{ civ_iterator.remove(); continue; }*/ } else //remove civilians that are not in a building { civ_iterator.remove(); continue; } if(civilian.isHPDefined()){ if(civilian.getHP()==0){ civ_iterator.remove(); continue; } } else { civ_iterator.remove(); continue; } if (civilianLocation instanceof AmbulanceTeam || civilianLocation instanceof Refuge ) { //remove this agent as it's not buried or there is no route to its civ_iterator.remove(); continue; } if(civilian.isBuriednessDefined()){ if(civilian.getBuriedness() == 0 && !(civilianLocation instanceof Building)){ //remove this agent as it's not buried or there is no route to its civ_iterator.remove(); continue; } if(!(civilian instanceof Civilian) && civilian.getBuriedness()==0){ civ_iterator.remove(); continue; } } else { civ_iterator.remove(); continue; } path = pathPlanner.findShortestPath(getID(),civilian.getID()); if(!path.isValid()){ civ_iterator.remove(); continue; } double travelTime = getSpeedInfo().getTimeToTravelPath(path); if (travelTime >=LONG_TRAVEL_TIME_IGNORE && getTimer().getTime() > IGNORE_UNTIL_TIME_STEP) { civ_iterator.remove(); continue; } double deadline = scheduler.getVictimDeadline(civilian); if (deadline <=0 ) civ_iterator.remove(); else civsWithPaths.add(new Task(civilian, path)); } } } return civsWithPaths; } private StandardEntity getLocation(){ return ((Human) me()).getPosition(getWorldModel()); } protected void sendUnload(int time) { AbstractIAMAgent.stopIfInterrupted(); this.getExecutionService().execute(new UnloadCommand()); } protected void sendRest(int time){ AbstractIAMAgent.stopIfInterrupted(); this.getExecutionService().execute(new RestCommand()); } protected void sendLoad(int time, Civilian target) { AbstractIAMAgent.stopIfInterrupted(); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - should be loading: " + target.getFullDescription()); this.getExecutionService().execute(new LoadCommand(target)); } protected void sendRescue(int time, Human target) { AbstractIAMAgent.stopIfInterrupted(); this.getExecutionService().execute(new DigOutCommand(target)); } protected void sendMove(int time, IPath path) { AbstractIAMAgent.stopIfInterrupted(); MoveCommand move = new MoveCommand(); move.setPath(path); this.getExecutionService().execute(move); } /** * Decide the action to execute in this time step * @return true if it did an action, false if it did not anything */ private boolean makeAction(ArrayList<Task> vics) { if(LOGGER.isTraceEnabled()) LOGGER.trace(" - doing something with "+target +" who is at " + target.getPosition().getValue() + " and I am at " + getLocation().getID().getValue()); boolean takenAction = false; boolean defined = target.isBuriednessDefined() && target.isHPDefined() && target.isPositionDefined() && !(getWorldModel().getEntity(target.getPosition()) instanceof AmbulanceTeam); if(!defined){ target=null; return false; } else if (target.getHP()==0){ if(loadedVictim){ sendUnload(timeStep); target = null; loadedVictim = false; return true; } else { target = null; loadedVictim = false; return false; } } if(loadedVictim)//it has a loaded victim { if(getLocation() instanceof Refuge)//leave the victim in the refuge { sendUnload(timeStep); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - unload victim:"+target); target = null; loadedVictim = false; takenAction=true; } else//bring the victim to the closest refuge { if(this.allRefuges.size()>0){ moveToClosestRefuge(); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - moving to refuge"); takenAction=true; } else { if(getLocation() instanceof Road) { sendUnload(timeStep); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - unload victim:"+target); target = null; loadedVictim = false; takenAction=true; } else { moveToClosestRoad(); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - moving to road to drop"); takenAction=true; } } } } else //it has not a loaded victim { StandardEntity targetPosition = getWorldModel().getEntity(target.getPosition()); if(targetPosition instanceof Refuge || targetPosition instanceof AmbulanceTeam || targetPosition == null)//target is just saved { target = null; takenAction =false; if(LOGGER.isTraceEnabled()) LOGGER.trace(" - "+target+" has been saved by someone else"); } else { if(getLocation()==targetPosition && targetPosition instanceof Building) { if(target.getBuriedness()==0)//VICTIM IS NOT buried { if(target instanceof Civilian && loadVictim()){ sendLoad(timeStep, (Civilian) target); loadedVictim = true; if(LOGGER.isTraceEnabled()) LOGGER.trace(" - loading victim: "+target); takenAction=true; } else { sendRest(timeStep); takenAction =true; if(LOGGER.isTraceEnabled()) LOGGER.trace(" - finished rescuing victim: "+target); target = null; } } else //victim is buried { sendRescue(timeStep, target); if(LOGGER.isTraceEnabled()) LOGGER.trace(" - rescuing victim: "+target); takenAction=true; } } else//move to victim { //find path path=null; for(Iterator<Task> it=vics.iterator(); it.hasNext();){ Task r = it.next(); if(r.civilian.getID().getValue()==target.getID().getValue()){ path = r.path; } } if (path == null) { path = pathPlanner.findShortestPath(getID(), target .getID()); } if (path.isValid()) { if(LOGGER.isTraceEnabled()) LOGGER.trace(" - moving to victim: "+target); //boolean tookRandomSearch = false; sendMove(timeStep, path); takenAction=true; } else { if(LOGGER.isTraceEnabled()) LOGGER.trace(" - path to target is null! and i cannot move to victim: "+target); target=null; takenAction=false; } } } } return takenAction; } /** * Load a civilian if it is unburied and move it to a close refuge */ private boolean loadVictim() { AmbulanceTeam tempAmb; if (target.getPosition().getValue() == getLocation().getID().getValue()) { for (int i = 0; i < team.length; ++i) { tempAmb = (AmbulanceTeam) team[i]; if (model.getEntity(tempAmb.getPosition()) instanceof Building && (tempAmb.getPosition().getValue() == target.getPosition().getValue())) { if (tempAmb.getID() == me().getID()){ return true; } else return false; } } return false; } return false; } /** * Move to a close refuge - usually called to save a humanoid or to go somewhere safe. * */ protected void moveToClosestRefuge() { path = pathPlanner.findShortestPath(getLocation().getID(), allRefuges); if (path.isValid()) { sendMove(timeStep, path); return; } else { //cant get to a refuge //sendRest(timeStep); doDefaultSearch(); return; } } protected void moveToClosestRoad(){ List<EntityID> neighbours = ((Area)getLocation()).getNeighbours(); if(getLocation() instanceof Road){ neighbours.add(getLocation().getID()); } path = pathPlanner.findShortestPath(getID(), neighbours); if(path.isValid()){ sendMove(timeStep, path); return; } else { sendRest(timeStep); return; } } /** * */ public class CivilianToSort { public StandardEntity civilian; public double deadline; public CivilianToSort(StandardEntity _civilian, double _deadline) { civilian = _civilian; deadline = _deadline; } } public class DeadlineComparator implements Comparator<CivilianToSort> { /** * Compares deadlines * @params d1 - first victim * @params d2 - second victim * @return a negative integer, zero or a positive integer * as the first argument's deadline is less, equal to, or greater than the second argument's deadline */ public int compare(CivilianToSort a, CivilianToSort b) { CivilianToSort vicA = (CivilianToSort) a; CivilianToSort vicB = (CivilianToSort ) b; double deadlineA = vicA.deadline; double deadlineB = vicB.deadline; if (deadlineA > deadlineB) return(1);//<=will sort in descending order of deadlines else if (deadlineA == deadlineB) return 0; else return(-1); } } public void postConnect() { super.postConnect(); //showWorldModelViewer(); // showRoutingViewer(); initialiseAmbulance(); addUpdateHandler(new AllocationHandler(this.getID().getValue(), scheduler)); } @Override protected void fallback(int time, ChangeSet changed) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(" " + getID().getValue() + " - DOING FALLBACK!"); } if(!teamSetUp){ team = getWorldModel().getEntitiesOfType(StandardEntityURN.AMBULANCE_TEAM).toArray(new AmbulanceTeam[0]); setMyIndex(team); scheduler.setmyIndex(myIndex); scheduler.setTeam(team); teamSetUp=true; if(LOGGER.isTraceEnabled()) printSharedID(); } //doDefaultSearch(); //return; // Am I transporting a civilian to a refuge? EntityID onb = someoneOnBoard(); if (onb !=null) { // Am I at a refuge? if (getLocation() instanceof Refuge) { // Unload! if (LOGGER.isTraceEnabled()) { LOGGER.trace(" unloading!"); } sendUnload(time); return; } else { // Move to a refuge IPath path = pathPlanner.findShortestPath(getLocation().getID(), allRefuges); if (path.isValid()) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(" moving to refuge!"); } sendMove(time, path); return; } // What do I do now? Might as well carry on and see if we can dig someone else out. if (LOGGER.isTraceEnabled()) { LOGGER.trace(" no refuges so searching!"); } doDefaultSearch(); return; } } //find out if someone is in the same position Human toSave = inThisPosition(); if (toSave !=null) { if ((toSave instanceof Civilian) && toSave.getBuriedness() == 0 && !(getLocation() instanceof Refuge)) { // Load if (LOGGER.isTraceEnabled()) { LOGGER.trace(" loading!"); } sendLoad(time, (Civilian)toSave); return; } if (toSave.getBuriedness() > 0) { // Rescue if (LOGGER.isTraceEnabled()) { LOGGER.trace(" rescuing!"); } sendRescue(time, toSave); return; } } else { // Try to move to the target ArrayList<EntityID> civs = new ArrayList<EntityID>(); for (StandardEntity next : getWorldModel().getEntitiesOfType(StandardEntityURN.CIVILIAN)) { civs.add(next.getID()); } IPath path = pathPlanner.findShortestPath(getLocation().getID(), civs); if (path.isValid()) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(" going to target!"); } sendMove(time, path); return; } } if (LOGGER.isTraceEnabled()) { LOGGER.trace(" searching with nothing to do!"); } doDefaultSearch(); return; } private EntityID someoneOnBoard() { for (StandardEntity next : getWorldModel().getEntitiesOfType(StandardEntityURN.CIVILIAN)) { if (((Human)next).getPosition().equals(getID())) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(" someone is onboard!"); } return next.getID(); } } return null; } private Human inThisPosition() { for (StandardEntity next : this.getWorldModel().getEntitiesOfType(StandardEntityURN.CIVILIAN)) { if (((Human)next).getPosition().equals(getLocation())) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(" someone is here!"); } return (Human)next; } } return null; } }//end of AladdinAmbulanceTeam class