package kernel; import java.util.Collection; import java.util.Map; import java.util.ArrayList; import rescuecore2.connection.Connection; import rescuecore2.connection.ConnectionListener; import rescuecore2.messages.Message; import rescuecore2.messages.Command; import rescuecore2.messages.control.KASense; import rescuecore2.worldmodel.Entity; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.ChangeSet; import rescuecore2.log.Logger; import rescuecore2.misc.collections.LazyMap; /** This class is the kernel interface to an agent. */ public class AgentProxy extends AbstractKernelComponent { private Entity entity; private Map<Integer, Collection<Command>> commands; /** Construct an agent. @param name The name of the controlling agent. @param e The entity controlled by the agent. @param c The connection to the agent. */ public AgentProxy(String name, Entity e, Connection c) { super(name, c); this.entity = e; commands = new LazyMap<Integer, Collection<Command>>() { @Override public Collection<Command> createValue() { return new ArrayList<Command>(); } }; c.addConnectionListener(new AgentConnectionListener()); } @Override public String toString() { return getName() + ": " + entity.getURN() + " " + entity.getID(); } /** Get the entity controlled by this agent. @return The entity controlled by this agent. */ public Entity getControlledEntity() { return entity; } /** Get all agent commands at a particular time. @param timestep The current timestep. @return A collection of messages representing the commands */ public Collection<Command> getAgentCommands(int timestep) { Collection<Command> result; synchronized (commands) { result = commands.get(timestep); } Logger.trace(entity.toString() + " getAgentCommands(" + timestep + ") returning " + result); return result; } /** Notify the of a perception update. @param time The current timestep. @param visible The set of visible changes. @param heard The set of communication messages that the agent heard. */ public void sendPerceptionUpdate(int time, ChangeSet visible, Collection<? extends Command> heard) { KASense sense = new KASense(getControlledEntity().getID(), time, visible, heard); send(sense); } /** Register an agent command received. @param c The command that was received. */ protected void commandReceived(Command c) { // Check that the command is for the right agent if (!c.getAgentID().equals(entity.getID())) { Logger.warn("Ignoring bogus command: Agent " + entity.getID() + " tried to send a command for agent " + c.getAgentID()); return; } int time = c.getTime(); Logger.trace("AgentProxy " + entity + " received " + c); synchronized (commands) { Collection<Command> result = commands.get(time); result.add(c); commands.notifyAll(); } } private class AgentConnectionListener implements ConnectionListener { @Override public void messageReceived(Connection c, Message msg) { if (msg instanceof Command) { EntityID id = ((Command)msg).getAgentID(); if (id.equals(getControlledEntity().getID())) { commandReceived((Command)msg); } } } } }