/**
   * 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 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;
  }