Problem with Array2DBase and MoveRandomWithin. Symptom: MoveRandomWithin rule in GAS_II_6 leaves agents in cells outside the specified area.
Array2DBase.findCells(Conditional, int, int, int, int) has incorrect limits on loops over coordinate space. Current code is:
<code>
for (int x = _x; x < width; x++) {
for (int y = _y; y < height; y++) {
</code>
and should be
<code>
for (int x = _x; x < _x + width; x++) {
for (int y = _y; y < _y + height; y++) {
</code>
Array2DBase.findRandomUnoccupied(int, int, int, int): if the first 10 guesses don't yield an unoccupied cell, then instead of searching for an unoccupied cell within the specified area, it searches for an unoccupied cell in the entire array.
Suggested fix: Change code from:
<code>
List available = findAvailable();
if (available.size() > 0) {
return (Node) available.get(randomToLimit(available.size()));
} else {
return null;
}
}
</code>
to
<code>
Conditional IS_AVAILABLE = new Conditional() {
private static final long serialVersionUID = 1L;
public final boolean meetsCondition(Object o) {
return ((Node) o).isAvailable();
}
};
Node[] available = findCells(IS_AVAILABLE, x, y, width, height);
if (available.length > 0) {
return (Node) available[randomToLimit(available.length)];
} else {
return null;
}
}
</code>
MoceRandomWithin(Agent): If called on an occupied cell within the specified range and there is no unoccupied cell within that range, behavior should return the original cell, not attempt calling moveTo with a null argument (this causes NullPointerException in GAS_II_6).
Suggested fix: Change from
<code>
((CellOccupant) agent).moveTo((HostCell) ((Array2D) ((CellOccupant) agent).getHostScape().getSpace()).findRandomUnoccupied(x, y, width, height));
</code>
to
<code>
HostCell newLocation = (HostCell) (((Array2D) ((CellOccupant) agent).getHostScape().getSpace()).findRandomUnoccupied(x, y, width, height));
if (newLocation == null) {
CoordinateDiscrete coord = (CoordinateDiscrete)((CellOccupant)agent).getCoordinate();
int agentX = coord.getValueAtDimension(1);
int agentY = coord.getValueAtDimension(2);
if ((x <= agentX) && (x+width > agentX) && (y <= agentY) && (y+height > agentY)) {
// agent is already within the specified area, but there are no vacant cells
// to move into, so return without doing anything.
return;
}
System.out.print("Can't find unoccupied cell.\n");
}
((CellOccupant) agent).moveTo(newLocation);
</code>
re: Array2DBase.findCells(Conditional, int, int, int, int)
Nice catch. Slipped past code coverage. Is this sued anywhere in the example models? I wonder if it is simply incorrectly documented. It's possible that the code really intends bounds for width and height.
re: Array2DBase.findRandomUnoccupied
yessh..
I don't really think I ever exercised these that much as from a modeling point of view it's a little questionable as it sort of assumes one is working with a Moore space. It would probably in general be better to use the distance methods instead wherever possible. How's that for a rationalization? :)
If you wanted to update the test code for these and give a patch, that would be most welcome. (or ahem, that committer thing..)