package biosim; import java.util.*; import java.awt.Dimension; public class Predator extends Organism { /** * A list of the Classes of Organisms that this Organism * finds appetizing. Note that this is a list of Objects that * are insantiations of class java.lang.Class. * * A more comete implementation might also include * something like a "yuckyList," to enable Predators * to specify exceptions: unappetizing or dangerous * Organisms, or perhaps just Organisms of the same * species. */ protected Vector preyList; /** * A list of Organisms that this Organism is currently * in the process of attacking. This a list of Objects that * are insantiations of class biosim.Organism. */ protected Vector victimList; // Some defaults we might want to change... // maxVelocity = 5.0; // birthRadius = 3.0; // growthRate = 0.05; // birthInterval = 25; // lifespan = 40; ///////////////////////////////////////////////////////////// /** * Construct a Predator at (px, py), in Ecosystem e, with random velocity in x and y */ public Predator(double px, double py, Ecosystem e) { super(px, py, e); preyList = new Vector(); initPreyList(); growthRate = 0.00; birthInterval = 50; lifespan = 70; maxVelocity = 7.0; victimList = new Vector(); } /** * Construct a Predator at (px, py), in Ecosystem e, with random velocity in x and y */ public Predator(int px, int py, Ecosystem e) { this((double) px, (double) py, e); } /** * Construct a Predator at (px, py), in Ecosystem e, with velocity vx and vy */ public Predator(double px, double py, double vx, double vy, Ecosystem e) { super(px, py, vx, vy, e); preyList = new Vector(); initPreyList(); growthRate = 0.00; birthInterval = 50; lifespan = 70; victimList = new Vector(); } /** * A predator, by default, keeps most of the * behavior of a generic Organism, as far as * the react() method is concerned. The only * method to which it responds uniquely is * COLLISIOIN. A predator sponds to COLLISION * events by attacking other organism, if * the other Organism belongs to a class on its * preyList. If attacked, the default Predator * will only die if the attacking Organism is bigger. */ public void react(EcoEvent e) { Organism other = e.from; switch (e.id) { case EcoEvent.COLLISION: { // Use the default method to adjust velocities. super.react(e); // See if the other Organism smells like food. if (this.preysOn(other)) { // Smells like food; let's attack! EcoEvent attack = new EcoEvent(EcoEvent.ATTACK, EcoEvent.NOW, other, this, null); ecosystem.schedule(attack); // Add the prey to our victimList, and hope it dies. victimList.addElement(other); } break; } case EcoEvent.ATTACK: { if (other.getRadius() > this.radius) { // Die, notifying both the Ecosystem and the attacker die(other); } else { EcoEvent resist = new EcoEvent(EcoEvent.RESIST, EcoEvent.NOW, other, this, null); ecosystem.schedule(resist); } break; } case EcoEvent.DEATH: { if (victimList.contains(other)) { // Our victim has died. Eat and be merry. grow(Math.sqrt(other.getRadius())); victimList.removeElement(other); } break; } case EcoEvent.RESIST: { if (victimList.contains(other)) { // Our victim resisted attack. Takf the list. victimList.removeElement(other); } break; } default: { super.react(e); break; } } } /** * This method, called by the constructor, allows a * Predator to specify which classes of Organisms it * finds appetizing. The default Predator will eat any kind * of Organism, including other Predators. */ public void initPreyList() { preyList = new Vector(); try { preyList.addElement(Class.forName("biosim.Organism")); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } } /** * Looks at the Class of the other Organism to determine if it is * on the preyList. If so, then it returns true. Otherwise, false. */ public boolean preysOn(Organism other) { for (int i = 0; i < preyList.size(); i++) { Class foodClass = (Class) preyList.elementAt(i); // Find out if any superclass of the other Organism // is in the preyList Class otherClass = other.getClass(); try { if (otherClass.equals(foodClass)) { return true; } do { otherClass = otherClass.getSuperclass(); if (otherClass.equals(foodClass)) { return true; } } while (! (otherClass.equals(Class.forName("biosim.Organism")))); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } } return false; } /** * Same as Organism.reproduce(), but calls the constructor * for Predator instead of Organism. */ protected void reproduce() { Vector offspring = new Vector(); double px = (velocity.x >= 0) ? position.x - radius - birthRadius : position.x + radius + birthRadius; double py = (velocity.y >= 0) ? position.y - radius - birthRadius : position.y + radius + birthRadius; // Create one new child. Predator child = new Predator(px, py, -velocity.x, -velocity.y, ecosystem); // Add the child to the offspring vector. offspring.addElement(child); // Create a BIRTH event to happen as soon as possible EcoEvent birth = new EcoEvent(EcoEvent.BIRTH, EcoEvent.NOW, null, this, offspring); // Tell the Ecosystem to schedule the birth event ecosystem.schedule(birth); } }