/*
* AP(r) Computer Science GridWorld Case Study:
* Copyright(c) 2005-2006 Cay S. Horstmann (http://horstmann.com)
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* @author Cay Horstmann
*/
package info.gridworld.actor;
import info.gridworld.grid.Location;
import java.util.ArrayList;
/**
* A Critter is an actor that moves through its world, processing
* other actors in some way and then picking a new location.
* The implementation of this class is testable on the AP CS A and AB exams.
*/
public class Critter extends Actor
{
/**
* A critter acts by getting a list of its neighbors, processing them,
* getting locations to move to, selecting one of them, and moving to the
* selected location.
*/
public void act()
{
if (getGrid() == null)
return;
ArrayList actors = getActors();
processActors(actors);
ArrayList moveLocs = getMoveLocations();
Location loc = selectMoveLocation(moveLocs);
makeMove(loc);
}
/**
* Gets the actors for processing. The actors must be contained in the same
* grid as this critter. Implemented to return the actors that occupy
* neighboring grid locations. Override this method in subclasses to look
* elsewhere for actors to process.
* @return a list of actors that are neighbors of this critter
*/
public ArrayList getActors()
{
return getGrid().getNeighbors(getLocation());
}
/**
* Processes the actors. Implemented to "eat" (i.e. remove) all actors that
* are not rocks or critters. Override this method in subclasses to process
* neighbors in a different way.
* Precondition: All objects in actors are contained in the
* same grid as this critter.
* @param actors the actors to be processed
*/
public void processActors(ArrayList actors)
{
for (Actor a : actors)
{
if (!(a instanceof Rock) && !(a instanceof Critter))
a.removeSelfFromGrid();
}
}
/**
* Gets the possible locations for the next move. Implemented to return the
* empty neighboring locations. Override this method in subclasses to look
* elsewhere for move locations.
* Postcondition: The locations must be valid in the grid of this critter.
* @return a list of possible locations for the next move
*/
public ArrayList getMoveLocations()
{
return getGrid().getEmptyAdjacentLocations(getLocation());
}
/**
* Selects the location for the next move. Implemented to randomly pick one
* of the possible locations, or to return the current location if
* locs has size 0. Override this method in subclasses that
* have another mechanism for selecting the next move location.
* Precondition: All locations in locs are valid in the grid
* of this critter
* @param locs the possible locations for the next move
* @return the location that was selected for the next move.
*/
public Location selectMoveLocation(ArrayList locs)
{
int n = locs.size();
if (n == 0)
return getLocation();
int r = (int) (Math.random() * n);
return locs.get(r);
}
/**
* Moves this critter to the given location. Implemented to call moveTo.
* Override this method in subclasses that want to carry out other actions
* for moving (for example, turning or leaving traces).
* Precondition: loc is valid in the grid of this critter
* @param loc the location to move to (must be valid)
*/
public void makeMove(Location loc)
{
moveTo(loc);
}
}