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

/* A rabbit ages, moves, breeds, and dies.
 * 
 * @author David J. Barnes and Michael Kolling
 * @version 2006.03.30
 */


import java.util.*;


public class Rabbit
{
  // 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();
    
  // rabbit characteristics
  private int age;
  private boolean isAlive;
  private Location location;


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

  public void run(Field updatedField, List<Rabbit> newRabbits)
  // A rabbit breeds, moves about, or dies of old age or overcrowding
  {
    incrementAge();    // may die
    if (isAlive) {
      int numBirths = breed();    // have rabbit breed
      for (int b = 0; b < numBirths; b++) {
        Rabbit newRabbit = new Rabbit(false);   // create new rabbit
        newRabbits.add(newRabbit);
        Location loc = updatedField.randomAdjLoc(location);
        newRabbit.setLocation(loc);
        updatedField.place(newRabbit, loc);     // place new rabbit in field
      }

      // try to move this rabbit
      Location newLoc = updatedField.freeAdjLoc(location);  // find a new location
      if (newLoc != null) {   // if new location is free
        setLocation(newLoc);
        updatedField.place(this, newLoc);
      }
      else  // can't move - so die due to overcrowding
        isAlive = false;
    }
  }  // end of run()

    
  private void incrementAge()
  // could result in the rabbit's death
  { age++;
    if (age > MAX_AGE)
      isAlive = false;
  }  // end of incrementAge()
    

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


  private boolean canBreed()
  // a rabbit can breed if it has reached the breeding age
  {  return (age >= BREEDING_AGE); }
    
  public boolean isAlive()
  {  return isAlive;  }

  public void setEaten()
  // tell the rabbit that it's dead now :(
  { isAlive = false; }
    
  public void setLocation(int row, int col)
  {  location = new Location(row, col);  }

  public void setLocation(Location loc)
  { location = loc; }

}  // end of Rabbit class
