
// Rabbit.java
// Andrew Davison, Nov 2018, ad@fivedots.coe.psu.ac.th

/* A rabbit ages, moves, breeds, and dies.

   This version inherits Animal.
   The inherited characteristics are accessed with get/set methods.
 * 
 * @author David J. Barnes and Michael Kolling
 * @version 2006.03.30
 */


import java.util.*;


public class Rabbit extends Animal
{
  // Characteristics shared by all rabbits (static fields).
  private static final int BREEDING_AGE = 5;
  private static final int MAX_AGE = 50;
  private static final double BREEDING_PROBABILITY = 0.15;
  private static final int MAX_LITTER_SIZE = 5; // max no. of births

  // A shared random number generator to control breeding.
  private static final Random rand = new Random();
 
  // all rabbit characteristics are inherited from Animal


  public Rabbit(boolean randomAge)
  // A new rabbit may be aged 0, or have a random age.
  {
    super();
    if (randomAge)
      setAge(rand.nextInt(MAX_AGE));
  }  // end of Rabbit()
    

  public void act(Field currentField, Field updatedField, List<Animal> newAnimals)
  /* A rabbit runs around. Sometimes it breeds or dies of old age.
     This was the former run() method in v.1. */
  {
    incrementAge();
    if (isAlive()) {
      int births = breed();
      for (int b = 0; b < births; b++) {
        Rabbit newRabbit = new Rabbit(false);
        newAnimals.add(newRabbit);
        newRabbit.setLocation(updatedField.randomAdjLoc(getLocation()));
        updatedField.place(newRabbit);
      }
      Location newLoc = updatedField.freeAdjLoc(getLocation());

      // Only transfer to the updated field if there was a free location
      if (newLoc != null) {
        setLocation(newLoc);
        updatedField.place(this);
      }
      else  // can neither move nor stay - overcrowding - all locations taken
        setDead();
    }
  }  // end of act()

    
  private void incrementAge()
  // could result in the rabbit's death
  {
    setAge(getAge() + 1);
    if (getAge() > MAX_AGE)
      setDead();
  } // end of incrementAge()

    
  private int breed()
  /* Generate a number representing the number of births,
     if the rabbit can breed. */
  {
    int births = 0;
    if (canBreed() && (rand.nextDouble() <= BREEDING_PROBABILITY))
      births = rand.nextInt(MAX_LITTER_SIZE) + 1;
    return births;
  }  // end of breed()

    
  public String toString()
  {  return "Rabbit, age " + getAge(); }

  private boolean canBreed()
  {  return (getAge() >= BREEDING_AGE); }

}  // end of Rabbit class
