package human;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.misc.Pair;
import rescuecore2.log.Logger;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.Area;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.components.StandardAgent;
import sample.SampleSearch;
import java.util.Collection;
import java.util.List;
import java.util.EnumSet;
/**
A basic police force agent that will try to clear a given target. Fully-blocked roads encountered along the way are also cleared. If there is no target then this agent does nothing.
*/
public class ControlledPoliceForce extends StandardAgent<PoliceForce> {
private SampleSearch search;
private Road target;
/**
Set the target for this police force.
@param target The new target.
*/
public void setTarget(Road target) {
this.target = target;
}
@Override
protected void think(int time, ChangeSet changed, Collection<Command> heard) {
if (location() instanceof Road) {
Road r = (Road)location();
EntityID nearest = getNearestBlockade();
if (nearest != null) {
sendClear(time, nearest);
return;
}
}
if (target == null) {
Logger.info("Nothing to do.");
return;
}
List<EntityID> path = search.breadthFirstSearch(me().getPosition(), target.getID());
if (path != null) {
sendMove(time, path);
return;
}
else {
Logger.info("Couldn't plan a path to target.");
}
}
@Override
protected EnumSet<StandardEntityURN> getRequestedEntityURNsEnum() {
return EnumSet.of(StandardEntityURN.POLICE_FORCE);
}
/**
Get the location of the entity controlled by this agent.
@return The location of the entity controlled by this agent.
*/
protected StandardEntity location() {
PoliceForce me = me();
return me.getPosition(model);
}
@Override
protected void postConnect() {
super.postConnect();
search = new SampleSearch(model);
}
@Override
public String toString() {
if (me() == null) {
return "Human controlled police force";
}
return "Human controlled police force " + getID() + (target == null ? " (no target)" : " target: road " + target.getID() + " with " + (target.isBlockadesDefined() ? " unknown" : String.valueOf(target.getBlockades().size())) + " blockades");
}
/**
Get the blockade that is nearest this agent.
@return The EntityID of the nearest blockade, or null if there are no blockades in the agents current location.
*/
public EntityID getNearestBlockade() {
return getNearestBlockade((Area)location(), me().getX(), me().getY());
}
/**
Get the blockade that is nearest a point.
@param area The area to check.
@param x The X coordinate to look up.
@param y The X coordinate to look up.
@return The EntityID of the nearest blockade, or null if there are no blockades in this area.
*/
public EntityID getNearestBlockade(Area area, int x, int y) {
double bestDistance = 0;
EntityID best = null;
if (area.isBlockadesDefined()) {
for (EntityID blockadeID : area.getBlockades()) {
StandardEntity entity = model.getEntity(blockadeID);
Pair<Integer, Integer> location = entity.getLocation(model);
if (location == null) {
continue;
}
double dx = location.first() - x;
double dy = location.second() - y;
double distance = Math.hypot(dx, dy);
if (best == null || distance < bestDistance) {
bestDistance = distance;
best = entity.getID();
}
}
}
return best;
}
}