/** * */ package iamrescue.agent.police.newstrategy; import iamrescue.agent.AbstractIAMAgent; import iamrescue.belief.StuckMemory.StuckInfo; import iamrescue.execution.command.ClearCommand; import iamrescue.execution.command.IPath; import iamrescue.execution.command.MoveCommand; import iamrescue.util.PositionXY; import iamrescue.util.blocks.BlockDetectionUtil; import iamrescue.util.comparators.EntityIDComparator; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; import javolution.util.FastSet; import org.apache.log4j.Logger; import rescuecore2.standard.entities.Area; import rescuecore2.standard.entities.Blockade; import rescuecore2.standard.entities.PoliceForce; import rescuecore2.standard.entities.Road; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.worldmodel.ChangeSet; import rescuecore2.worldmodel.EntityID; /** * @author Sebastian * */ public class NewClosestTargetPoliceForce extends AbstractIAMAgent<PoliceForce> { private static final String DISTANCE_KEY = "clear.repair.distance"; private static final boolean SHOW_ROUTING = false; private static final int VERY_CLOSE = 100; private static final boolean CLEAR_ON_RANDOM_MOVE = true; private static final int RANDOM_MOVE_DISTANCE_CLEAR = 5000; private int clearDistance; private int veryClose; private static final double RECOMPUTE_THRESHOLD = 0.2; private TaskAllocator taskAllocator; private FutureClearingRoutingModule clearingModule; private Collection<EntityID> refuges; private static final Logger LOGGER = Logger .getLogger(NewClosestTargetPoliceForce.class); private double lastDistancePerTimeStep = 0; private ChangeSet lastChanged; private Set<EntityID> stuckPositions = new FastSet<EntityID>(); // private boolean iPreferRefuges = false; private boolean iPreferPoliceForces = false; private boolean iPreferAmbulanceTeams = false; private boolean iPreferFireBrigades = false; private boolean didDesparateClearLastTime = false; // private ISpatialIndex spatialIndex; @Override protected void postConnect() { super.postConnect(); taskAllocator = new TaskAllocator(getWorldModel(), getTimer(), config, getSpeedInfo(), me().getID()); clearingModule = taskAllocator.getClearingModule(); lastDistancePerTimeStep = getSpeedInfo().getDistancePerTimeStep(); Collection<StandardEntity> refugeList = getWorldModel() .getEntitiesOfType(StandardEntityURN.REFUGE); refuges = new ArrayList<EntityID>(refugeList.size()); for (StandardEntity standardEntity : refugeList) { refuges.add(standardEntity.getID()); } clearDistance = config.getIntValue(DISTANCE_KEY); veryClose = (VERY_CLOSE < clearDistance) ? VERY_CLOSE : clearDistance; // showRoutingViewer(); // showWorldModelViewer(); if (SHOW_ROUTING) { Collection<StandardEntity> entitiesOfType = getWorldModel() .getEntitiesOfType(StandardEntityURN.POLICE_FORCE); List<StandardEntity> entities = new ArrayList<StandardEntity>( entitiesOfType); Collections.sort(entities, EntityIDComparator.DEFAULT_INSTANCE); if (entities.get(0).equals(me())) { showRoutingViewer(); } } StandardEntityURN myPreferredTarget = TeamSplitter .getMyPreferredTarget(getWorldModel(), me().getID(), 1, 1, 1); if (myPreferredTarget.equals(StandardEntityURN.POLICE_FORCE)) { iPreferPoliceForces = true; } else if (myPreferredTarget.equals(StandardEntityURN.AMBULANCE_TEAM)) { iPreferAmbulanceTeams = true; } else { iPreferFireBrigades = true; } // spatialIndex = new SpatialIndex(getWorldModel()); } @Override protected List<StandardEntityURN> getAgentTypes() { return Collections.singletonList(StandardEntityURN.POLICE_FORCE); } private boolean reachedFirst = false; @Override protected void think(int time, ChangeSet changed) { lastChanged = changed; checkRoutingRecompute(); boolean ok = false; if (me().getDamage() > 0) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("I am damaged. Heading to refuge"); } clearPathTo(refuges); return; } Set<EntityID> stuckAgents = getWorldModel().getStuckMemory() .getStuckAgents(); if (stuckAgents.size() > 0) { // Get closest double closestDistance = Double.POSITIVE_INFINITY; EntityID closest = null; PositionXY myXY = new PositionXY(me().getLocation(getWorldModel())); for (EntityID id : stuckAgents) { StuckInfo stuckInfo = getWorldModel().getStuckMemory() .getStuckInfo(id); PositionXY xy = new PositionXY(getWorldModel().getEntity( stuckInfo.getPosition()).getLocation(getWorldModel())); double distance = xy.distanceTo(myXY); if (distance < closestDistance) { closestDistance = distance; closest = stuckInfo.getPosition(); } } if (closest != null) { LOGGER.info("Moving to stuck agent at position: " + closest); clearPathTo(closest); return; } } StandardEntity closestGoal = taskAllocator.computeClosestGoal(me()); if (closestGoal != null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Heading towards goal " + closestGoal.getFullDescription()); } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("No valid goal found"); } } if (closestGoal != null) { if (closestGoal.equals(me())) { // Need to clear path to refuge ok = clearPathTo(refuges); } else { ok = clearPathTo(closestGoal.getID()); } } if (!ok) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Doing searching instead."); } doDefaultSearch(); } } private void checkRoutingRecompute() { double distancePerTimeStep = getSpeedInfo().getDistancePerTimeStep(); if (lastDistancePerTimeStep != 0 && Math.abs(distancePerTimeStep - lastDistancePerTimeStep) / lastDistancePerTimeStep >= RECOMPUTE_THRESHOLD) { long time = 0; if (LOGGER.isTraceEnabled()) { LOGGER.trace("Recomputing graph"); time = System.nanoTime(); } Collection<StandardEntity> areas = getWorldModel() .getEntitiesOfType(StandardEntityURN.ROAD, StandardEntityURN.BUILDING, StandardEntityURN.FIRE_STATION, StandardEntityURN.POLICE_OFFICE, StandardEntityURN.AMBULANCE_CENTRE, StandardEntityURN.REFUGE); for (StandardEntity area : areas) { clearingModule.forceRecompute((Area) area); } lastDistancePerTimeStep = distancePerTimeStep; if (LOGGER.isTraceEnabled()) { LOGGER.trace("Recomputing graph took " + (System.nanoTime() - time) + "ns"); } } } /** * @param id */ private boolean clearPathTo(EntityID id) { return clearPathTo(Collections.singleton(id)); } private boolean clearPathTo(Collection<EntityID> targets) { IPath path = clearingModule.findShortestPath(me().getID(), targets); if (!path.isValid()) { return false; } PositionXY myPosition = new PositionXY(me() .getLocation(getWorldModel())); List<Blockade> blocksToClear = BlockDetectionUtil .findObstructingBlockades(path, getWorldModel()); Blockade blockToClear = null; for (Blockade block : blocksToClear) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Block: " + block); } if (BlockDetectionUtil.isWithinDistanceToBlockade(myPosition, block, clearDistance)) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("In range!"); } if (lastChanged.getChangedEntities().contains(block.getID())) { blockToClear = block; if (LOGGER.isTraceEnabled()) { LOGGER.trace("Found block on path to goal: " + blockToClear); } } break; } else { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Not in range: " + BlockDetectionUtil.getDistanceToBlockade( myPosition, block)); } } } if (blockToClear == null) { // Check if very close to block /* * Collection<StandardEntity> query = getSpatialIndex().query( * SpatialQueryFactory.queryWithinDistance(myPosition, veryClose, * Blockade.class)); */ int tempVeryClose = veryClose; if (CLEAR_ON_RANDOM_MOVE && (didDesparateClearLastTime || getExecutionService() .getLastRandomMoveTime() >= getTimer().getTime() - 2)) { didDesparateClearLastTime = true; tempVeryClose = Math.min(clearDistance, RANDOM_MOVE_DISTANCE_CLEAR); } Collection<StandardEntity> objectsInRange = getWorldModel() .getObjectsInRange(me(), tempVeryClose); for (StandardEntity entity : objectsInRange) { if (entity instanceof Road) { Road road = (Road) entity; if (road.isBlockadesDefined()) { List<EntityID> blockades = road.getBlockades(); for (EntityID blockID : blockades) { Blockade block = (Blockade) getWorldModel() .getEntity(blockID); if (lastChanged.getChangedEntities().contains( block.getID()) && BlockDetectionUtil .isWithinDistanceToBlockade( myPosition, block, clearDistance)) { blockToClear = (Blockade) block; if (LOGGER.isDebugEnabled()) { LOGGER.debug("I'm very close to a block: " + blockToClear); } break; } } } } } // This is reset if no block was found didDesparateClearLastTime = false; } else { didDesparateClearLastTime = false; } if (blockToClear != null) { getExecutionService().execute(new ClearCommand(blockToClear)); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Moving towards goal: " + path.toVerboseString()); } getExecutionService().execute(new MoveCommand(path)); } return true; } /* * (non-Javadoc) * * @see iamrescue.agent.AbstractIAMAgent#fallback(int, * rescuecore2.worldmodel.ChangeSet) */ @Override protected void fallback(int time, ChangeSet changed) { // TODO Auto-generated method stub } }