/** * */ package iamrescue.agent.police.newstrategy; import iamrescue.agent.ISimulationTimer; import iamrescue.belief.IAMWorldModel; import iamrescue.routing.AbstractRoutingModule; import iamrescue.routing.WorldModelConverter; import iamrescue.routing.WorldModelConverter.SimpleGraphNode; import iamrescue.routing.WorldModelConverter.WorldModelArea; import iamrescue.routing.costs.IRoutingCostFunction; import iamrescue.routing.costs.PassableRoutingCostFunction; import iamrescue.routing.dijkstra.DijkstrasShortestPath; import iamrescue.routing.dijkstra.SimpleDijkstrasRoutingModule; import iamrescue.routing.dijkstra.SimpleGraph; import iamrescue.routing.util.ISpeedInfo; import iamrescue.util.PositionXY; import iamrescue.util.comparators.EntityIDComparator; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import javolution.util.FastList; import javolution.util.FastSet; import rescuecore2.config.Config; import rescuecore2.standard.entities.AmbulanceTeam; import rescuecore2.standard.entities.Area; import rescuecore2.standard.entities.Building; import rescuecore2.standard.entities.Civilian; import rescuecore2.standard.entities.FireBrigade; import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.PoliceForce; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.WorldModel; import rescuecore2.worldmodel.WorldModelListener; /** * @author Sebastian * */ public class GoalGenerator implements WorldModelListener<StandardEntity> { private AbstractRoutingModule freeRouting; private List<Integer> refugeSourceList; private List<Double> refugeCostList; private List<StandardEntity> policeForces; private List<StandardEntity> ambulanceAgents; private List<StandardEntity> fireBrigadeAgents; private List<StandardEntity> civilians; private IAMWorldModel worldModel; private IRoutingCostFunction freeRoutingCostFunction; private ISimulationTimer timer; private List<StandardEntity> refuges; private Config config; private ISpeedInfo speedInfo; private EntityID myID; public GoalGenerator(IAMWorldModel worldModel, ISimulationTimer timer, Config config, ISpeedInfo speedInfo) { this(worldModel, timer, config, speedInfo, null); } public GoalGenerator(IAMWorldModel worldModel, ISimulationTimer timer, Config config, ISpeedInfo speedInfo, EntityID myID) { this.myID = myID; this.config = config; this.speedInfo = speedInfo; this.timer = timer; this.worldModel = worldModel; this.freeRoutingCostFunction = new PassableRoutingCostFunction(1, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, worldModel); this.freeRouting = new SimpleDijkstrasRoutingModule(worldModel, freeRoutingCostFunction, timer); // clearingModule = new FutureClearingRoutingModule(config, timer, // worldModel, speedInfo); // this.myID = myID; // Get all police agents policeForces = new ArrayList<StandardEntity>(); policeForces.addAll(worldModel .getEntitiesOfType(StandardEntityURN.POLICE_FORCE)); // Get other agents fireBrigadeAgents = new ArrayList<StandardEntity>(); fireBrigadeAgents.addAll(worldModel .getEntitiesOfType(StandardEntityURN.FIRE_BRIGADE)); ambulanceAgents = new ArrayList<StandardEntity>(); ambulanceAgents.addAll(worldModel .getEntitiesOfType(StandardEntityURN.AMBULANCE_TEAM)); // Civilians civilians = new ArrayList<StandardEntity>(); civilians.addAll(worldModel .getEntitiesOfType(StandardEntityURN.CIVILIAN)); refuges = new ArrayList<StandardEntity>(); refuges.addAll(worldModel.getEntitiesOfType(StandardEntityURN.REFUGE)); if (refuges.size() == 0) { // Clear from initial police force positions then for (StandardEntity standardEntity : policeForces) { refuges.add(worldModel.getEntity(((Human) standardEntity) .getPosition())); } } Collections.sort(policeForces, EntityIDComparator.DEFAULT_INSTANCE); Collections .sort(fireBrigadeAgents, EntityIDComparator.DEFAULT_INSTANCE); Collections.sort(ambulanceAgents, EntityIDComparator.DEFAULT_INSTANCE); Collections.sort(civilians, EntityIDComparator.DEFAULT_INSTANCE); Collections.sort(refuges, EntityIDComparator.DEFAULT_INSTANCE); worldModel.addWorldModelListener(this); // Extract converter WorldModelConverter converter = freeRouting.getConverter(); // Get all sources Set<Integer> sources = new FastSet<Integer>(); for (StandardEntity refuge : refuges) { WorldModelArea worldModelArea = converter.getWorldModelArea(refuge .getID().getValue()); sources.addAll(worldModelArea.getSimpleNeighbours()); } refugeSourceList = new ArrayList<Integer>(sources.size()); refugeCostList = new ArrayList<Double>(sources.size()); for (Integer id : sources) { refugeSourceList.add(id); refugeCostList.add(0.0); } } public GoalContainer generateGoals() { // Extract graph SimpleGraph graph = freeRouting.getGraph(); WorldModelConverter converter = freeRouting.getConverter(); // Run complete Dijkstra DijkstrasShortestPath dijkstra = new DijkstrasShortestPath(graph, refugeSourceList, refugeCostList); /*DijkstrasShortestPath dijkstraFromMe; if (myID != null) { dijkstraFromMe = new DijkstrasShortestPath(graph, converter .getSimpleGraphIDs(myID)); }*/ dijkstra.forceFullCompute(); GoalContainer goals = new GoalContainer(); List<StandardEntity> agents = new FastList<StandardEntity>(); agents.addAll(policeForces); agents.addAll(fireBrigadeAgents); agents.addAll(ambulanceAgents); List<StandardEntity> agentsToClear = extractGoals(agents, dijkstra, converter); for (StandardEntity agent : agentsToClear) { if (agent instanceof PoliceForce) { goals.addPoliceForce((PoliceForce) agent); } else if (agent instanceof AmbulanceTeam) { goals.addAmbulanceTeam((AmbulanceTeam) agent); } else { goals.addFireBrigade((FireBrigade) agent); } // goals.addAgent((Human) agent); } List<StandardEntity> civiliansToClear = extractGoals(civilians, dijkstra, converter); for (StandardEntity civilian : civiliansToClear) { goals.addCivilian((Civilian) civilian); } List<EntityID> unsearched = new FastList<EntityID>(); unsearched.addAll(worldModel.getUnknownBuildings()); unsearched.addAll(worldModel.getSafeUnsearchedBuildings()); for (EntityID entityID : unsearched) { StandardEntity se = worldModel.getEntity(entityID); if (needsClearing(se, dijkstra, converter)) { goals.addUnsearchedBuilding((Building) se); } } // TODO: Add burning buildings here return goals; } private List<StandardEntity> extractGoals( List<StandardEntity> potentialTargets, DijkstrasShortestPath dijkstra, WorldModelConverter converter) { List<StandardEntity> needClearing = new FastList<StandardEntity>(); for (StandardEntity standardEntity : potentialTargets) { if (needsClearing(standardEntity, dijkstra, converter)) { needClearing.add(standardEntity); } } return needClearing; } private boolean needsClearing(StandardEntity poi, DijkstrasShortestPath dijkstra, WorldModelConverter converter) { StandardEntity position; if (poi instanceof Human) { Human human = (Human) poi; if (!(human.isPositionDefined() && (!human.isHPDefined() || human .getHP() > 0))) { // Ignore if position undefined or dead return false; } position = worldModel.getEntity(human.getPosition()); if (position instanceof Human) { // Loaded on ambulance? Human h = (Human) position; if (h.isPositionDefined()) { position = worldModel.getEntity(h.getPosition()); } else { return false; } } } else { position = poi; } // Get position WorldModelArea worldModelArea = converter.getWorldModelArea(position .getID().getValue()); Set<Integer> simpleNeighbours = worldModelArea.getSimpleNeighbours(); // Need to check simple neighbours boolean free = false; for (int neighbour : simpleNeighbours) { // Check if free // System.out.println("Cost to " + neighbour + ": " // + dijkstra.getCost(neighbour)); if (dijkstra.getCost(neighbour) < Double.POSITIVE_INFINITY) { if (poi instanceof Human) { SimpleGraphNode simpleGraphNode = converter .getSimpleGraphNode(neighbour); // Now check if possible to reach agent on node PositionXY representativePoint = simpleGraphNode .getRepresentativePoint(); double travelCost = freeRoutingCostFunction.getTravelCost( (Area) position, representativePoint, new PositionXY(poi.getLocation(worldModel))); // System.out.println("Cost between " + representativePoint // + " and " // + new PositionXY(poi.getLocation(worldModel)) // + ": " + travelCost); if (travelCost < Double.POSITIVE_INFINITY) { free = true; break; } } else { free = true; break; } } } // Done checking return !free; } /* * (non-Javadoc) * * @see * rescuecore2.worldmodel.WorldModelListener#entityAdded(rescuecore2.worldmodel * .WorldModel, rescuecore2.worldmodel.Entity) */ @Override public void entityAdded(WorldModel<? extends StandardEntity> model, StandardEntity e) { if (e instanceof Civilian) { civilians.add(e); Collections.sort(civilians, EntityIDComparator.DEFAULT_INSTANCE); } } @Override public void entityRemoved(WorldModel<? extends StandardEntity> model, StandardEntity e) { // Shouldn't happen } }