/* 
 * 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 moving to a new location. Define your own
 * critters by extending this class and overriding any methods of this class
 * except for act. When you override these methods, be sure to
 * preserve the postconditions. 
* 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 other actors, processing that list, * 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. Implemented to return the actors that * occupy neighboring grid locations. Override this method in subclasses to * look elsewhere for actors to process.
* Postcondition: The state of all actors is unchanged. * @return a list of actors that this critter wishes to process. */ public ArrayList getActors() { return getGrid().getNeighbors(getLocation()); } /** * Processes the elements of actors. New actors may be added * to empty locations. Implemented to "eat" (i.e. remove) selected actors * that are not rocks or critters. Override this method in subclasses to * process actors in a different way.
* Postcondition: (1) The state of all actors in the grid other than this * critter and the elements of actors is unchanged. (2) The * location of this critter is unchanged. * @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 a list of possible locations for the next move. These locations must * be valid in the grid of this critter. Implemented to return the empty * neighboring locations. Override this method in subclasses to look * elsewhere for move locations.
* Postcondition: The state of all actors is unchanged. * @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.
* Postcondition: (1) The returned location is an element of * locs, this critter's current location, or * null. (2) The state of all actors is unchanged. * @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 loc, or removes * this critter from its grid if loc is null. * An actor may be added to the old location. If there is a different actor * at location loc, that actor is removed from the grid. * Override this method in subclasses that want to carry out other actions * (for example, turning this critter or adding an occupant in its previous * location).
* Postcondition: (1) getLocation() == loc. (2) The state of * all actors other than those at the old and new locations is unchanged. * @param loc the location to move to */ public void makeMove(Location loc) { if (loc == null) removeSelfFromGrid(); else moveTo(loc); } }