/** * Returns the position of each agent after accounting for collisions that are a result of agents * trying to move into each others previous locations. * * @param originalPositions the original position of the agents before their actions were taken. * @param desiredPositions the new position the agents are trying to go into * @return the positions of the agents accounting for collisions. */ protected List<Location2> resolvePositionSwaps( List<Location2> originalPositions, List<Location2> desiredPositions) { List<Location2> resolvedPositions = new ArrayList<GridGameStandardMechanics.Location2>(desiredPositions); List<Location2> newNoopPositions = new ArrayList<GridGameStandardMechanics.Location2>(); for (int i = 0; i < originalPositions.size(); i++) { Location2 a1op = originalPositions.get(i); Location2 a1dp = resolvedPositions.get(i); for (int j = i + 1; j < resolvedPositions.size(); j++) { Location2 a2op = originalPositions.get(j); Location2 a2dp = resolvedPositions.get(j); if (a1op.equals(a2dp) && a1dp.equals(a2op)) { // swap collision! resolvedPositions.set(i, new Location2(a1op)); resolvedPositions.set(j, new Location2(a2op)); newNoopPositions.add(a1op); newNoopPositions.add(a2op); break; } } } if (newNoopPositions.size() > 0) { return this.backupNoOps(originalPositions, resolvedPositions, newNoopPositions); } return resolvedPositions; }
/** * Returns a movement result of the agent. If the agent tries to pass through a semi-wall, then it * is randomly selected whether the agent succeeds or not. If the agent tries to move through a * solid wall or to a location where there is another agent who is not moving, then no change * occurs. * * @param s the state containing the agent * @param p0 the initial position of the agent * @param delta the desired change of position. * @param agentNoOpLocs the locations occupied by agents who are not moving. * @return The resulting location of this agents movement. */ protected Location2 sampleBasicMovement( State s, Location2 p0, Location2 delta, List<Location2> agentNoOpLocs) { Location2 p1 = p0.add(delta); boolean reset = false; for (Location2 anl : agentNoOpLocs) { if (p1.equals(anl)) { reset = true; break; } } if (delta.x != 0 && !reset) { reset = this.sampleWallCollision(p0, delta, s.getObjectsOfClass(GridGame.CLASSDIMVWALL), true); } if (delta.y != 0 && !reset) { reset = this.sampleWallCollision(p0, delta, s.getObjectsOfClass(GridGame.CLASSDIMHWALL), false); } if (reset) { p1 = p1.subtract(delta); } return p1; }
/** * Returns with whom each agent is in a collision competition for a cell. * * @param candidatePositions a list of the positions to which each agent would like to go; the * Location2 in index 1 indicates the location the 1th index agent wants to go to. * @return A map from the index of each agent to a list of the index of agents with whom there is * competition for a cell */ protected Map<Integer, List<Integer>> getColissionSets(List<Location2> candidatePositions) { Map<Integer, List<Integer>> collisionSets = new HashMap<Integer, List<Integer>>(); for (int i = 0; i < candidatePositions.size(); i++) { Location2 candLoc = candidatePositions.get(i); List<Integer> collisions = new ArrayList<Integer>(); collisions.add(i); for (int j = i + 1; j < candidatePositions.size(); j++) { if (collisionSets.containsKey(j)) { continue; // already found collisions with this agent } Location2 cLoc = candidatePositions.get(j); if (candLoc.equals(cLoc)) { collisions.add(j); } } if (collisions.size() > 1) { // greater than one because an agent always "collides" with itself // set the collision set for each agent involved for (Integer aid : collisions) { collisionSets.put(aid, collisions); } } } return collisionSets; }
/** * Returns the list of possible outcome locations for a given start point and desired position * change. * * @param s the state in which the changes would occur * @param p0 the initial location * @param delta the desired change in position * @param agentNoOpLocs the locations occupied by agents who are not moving * @return the list of possible outcome locations in which the agent could wind up */ protected List<Location2Prob> getPossibleLocationsFromWallCollisions( State s, Location2 p0, Location2 delta, List<Location2> agentNoOpLocs) { List<Location2Prob> locs = new ArrayList<GridGameStandardMechanics.Location2Prob>(2); Location2 p1 = p0.add(delta); for (Location2 anl : agentNoOpLocs) { if (p1.equals(anl)) { // definitely cannot move to desired position p1 = p1.subtract(delta); locs.add(new Location2Prob(p1, 1.)); return locs; } } if (delta.x != 0) { int wc = this.wallCollision(p0, delta, s.getObjectsOfClass(GridGame.CLASSDIMVWALL), true); if (wc == 0) { locs.add(new Location2Prob(p1, 1.)); // agent freely moves } else if (wc == 1) { p1 = p1.subtract(delta); locs.add(new Location2Prob(p1, 1.)); // agent certainly cannot move } else { // agent moves with some probability locs.add(new Location2Prob(p1, this.pMoveThroughSWall)); locs.add(new Location2Prob(p1.subtract(delta), 1. - this.pMoveThroughSWall)); } } else if (delta.y != 0) { int wc = this.wallCollision(p0, delta, s.getObjectsOfClass(GridGame.CLASSDIMHWALL), false); if (wc == 0) { locs.add(new Location2Prob(p1, 1.)); // agent freely moves } else if (wc == 1) { p1 = p1.subtract(delta); locs.add(new Location2Prob(p1, 1.)); // agent certainly cannot move } else { // agent moves with some probability locs.add(new Location2Prob(p1, this.pMoveThroughSWall)); locs.add(new Location2Prob(p1.subtract(delta), 1. - this.pMoveThroughSWall)); } } else { // agent is not trying to change location locs.add(new Location2Prob(p1, 1.)); } return locs; }
/** * Backups position changes by agents which can no longer move to their desired location. That is, * if agent a wanted to move to cell z, but failed for some reason (e.g., direct collision with * another agent), then z would be added to the noops list and this method would back up the * effect of a's ability to change position to any agents that wanted to move into a's position. * * @param originalPositions the original position of agents in the previous state * @param desiredPositions the desired position where the agents want to go * @param noops the locations in which agents have been forced to stay from other events * @return the new resolved locations of all agents */ List<Location2> backupNoOps( List<Location2> originalPositions, List<Location2> desiredPositions, List<Location2> noops) { List<Location2> resolved = new ArrayList<GridGameStandardMechanics.Location2>(desiredPositions); boolean needsUpdating = true; while (needsUpdating) { needsUpdating = false; for (int i = 0; i < resolved.size(); i++) { Location2 dl = resolved.get(i); Location2 ol = originalPositions.get(i); if (!dl.equals(ol) && noops.contains(dl)) { resolved.set(i, ol); noops.add(ol); needsUpdating = true; } } } return resolved; }