package aima.core.environment.xyenv; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import aima.core.agent.Action; import aima.core.agent.Agent; import aima.core.agent.EnvironmentObject; import aima.core.agent.EnvironmentState; import aima.core.agent.Percept; import aima.core.agent.impl.AbstractEnvironment; import aima.core.agent.impl.DynamicPercept; import aima.core.util.datastructure.XYLocation; /** * @author Ravi Mohan * @author Ciaran O'Reilly */ public class XYEnvironment extends AbstractEnvironment { private XYEnvironmentState envState = null; // // PUBLIC METHODS // public XYEnvironment(int width, int height) { assert (width > 0); assert (height > 0); envState = new XYEnvironmentState(width, height); } @Override public EnvironmentState getCurrentState() { return envState; } @Override public EnvironmentState executeAction(Agent a, Action action) { return envState; } @Override public Percept getPerceptSeenBy(Agent anAgent) { return new DynamicPercept(); } public void addObjectToLocation(EnvironmentObject eo, XYLocation loc) { moveObjectToAbsoluteLocation(eo, loc); } public void moveObjectToAbsoluteLocation(EnvironmentObject eo, XYLocation loc) { // Ensure the object is not already at a location envState.moveObjectToAbsoluteLocation(eo, loc); // Ensure is added to the environment addEnvironmentObject(eo); } public void moveObject(EnvironmentObject eo, XYLocation.Direction direction) { XYLocation presentLocation = envState.getCurrentLocationFor(eo); if (null != presentLocation) { XYLocation locationToMoveTo = presentLocation.locationAt(direction); if (!(isBlocked(locationToMoveTo))) { moveObjectToAbsoluteLocation(eo, locationToMoveTo); } } } public XYLocation getCurrentLocationFor(EnvironmentObject eo) { return envState.getCurrentLocationFor(eo); } public Set<EnvironmentObject> getObjectsAt(XYLocation loc) { return envState.getObjectsAt(loc); } public Set<EnvironmentObject> getObjectsNear(Agent agent, int radius) { return envState.getObjectsNear(agent, radius); } public boolean isBlocked(XYLocation loc) { for (EnvironmentObject eo : envState.getObjectsAt(loc)) { if (eo instanceof Wall) { return true; } } return false; } public void makePerimeter() { for (int i = 0; i < envState.width; i++) { XYLocation loc = new XYLocation(i, 0); XYLocation loc2 = new XYLocation(i, envState.height - 1); envState.moveObjectToAbsoluteLocation(new Wall(), loc); envState.moveObjectToAbsoluteLocation(new Wall(), loc2); } for (int i = 0; i < envState.height; i++) { XYLocation loc = new XYLocation(0, i); XYLocation loc2 = new XYLocation(envState.width - 1, i); envState.moveObjectToAbsoluteLocation(new Wall(), loc); envState.moveObjectToAbsoluteLocation(new Wall(), loc2); } } } class XYEnvironmentState implements EnvironmentState { int width; int height; private Map<XYLocation, Set<EnvironmentObject>> objsAtLocation = new LinkedHashMap<XYLocation, Set<EnvironmentObject>>(); public XYEnvironmentState(int width, int height) { this.width = width; this.height = height; for (int h = 1; h <= height; h++) { for (int w = 1; w <= width; w++) { objsAtLocation.put(new XYLocation(h, w), new LinkedHashSet<EnvironmentObject>()); } } } public void moveObjectToAbsoluteLocation(EnvironmentObject eo, XYLocation loc) { // Ensure is not already at another location for (Set<EnvironmentObject> eos : objsAtLocation.values()) { if (eos.remove(eo)) { break; // Should only every be at 1 location } } // Add it to the location specified getObjectsAt(loc).add(eo); } public Set<EnvironmentObject> getObjectsAt(XYLocation loc) { Set<EnvironmentObject> objectsAt = objsAtLocation.get(loc); if (null == objectsAt) { // Always ensure an empty Set is returned objectsAt = new LinkedHashSet<EnvironmentObject>(); objsAtLocation.put(loc, objectsAt); } return objectsAt; } public XYLocation getCurrentLocationFor(EnvironmentObject eo) { for (XYLocation loc : objsAtLocation.keySet()) { if (objsAtLocation.get(loc).contains(eo)) { return loc; } } return null; } public Set<EnvironmentObject> getObjectsNear(Agent agent, int radius) { Set<EnvironmentObject> objsNear = new LinkedHashSet<EnvironmentObject>(); XYLocation agentLocation = getCurrentLocationFor(agent); for (XYLocation loc : objsAtLocation.keySet()) { if (withinRadius(radius, agentLocation, loc)) { objsNear.addAll(objsAtLocation.get(loc)); } } // Ensure the 'agent' is not included in the Set of // objects near objsNear.remove(agent); return objsNear; } @Override public String toString() { return "XYEnvironmentState:" + objsAtLocation.toString(); } // // PRIVATE METHODS // private boolean withinRadius(int radius, XYLocation agentLocation, XYLocation objectLocation) { int xdifference = agentLocation.getXCoOrdinate() - objectLocation.getXCoOrdinate(); int ydifference = agentLocation.getYCoOrdinate() - objectLocation.getYCoOrdinate(); return Math.sqrt((xdifference * xdifference) + (ydifference * ydifference)) <= radius; } }