/*----------------------------------------------------------------------+
|      Title:	Range.java                                              |
|                                                                       |
|      Author:	David E. Joyce                                          |
|           Department of Mathematics and Computer Science              |
|           Clark University                                            |
|           Worcester, MA 01610-1477                                    |
|           U.S.A.                                                      |
|                                                                       |
|           http://aleph0.clarku.edu/~djoyce/                           |
|           djoyce@clarku.edu                                           |
|                                                                       |
|      Date:    May, 2002.                                              |
+----------------------------------------------------------------------*/



import java.awt.*;

public class Range {

  private int population;
  int numberOfHerds;
  int selectedHerd;
  int day;

  Herd herd[];
  Genome L[][], R[][]; // the left- and right-moving bands
  int Lvitals[][], Rvitals[][]; // and their vitalities
  int leave[]; // their sizes
  Stats stats[][];

  public Range (int initialPopulation, int maximumPopulation,
                int numberOfHerds, int initialVitality) {
    this.population = initialPopulation;
    if (numberOfHerds < 1)
      numberOfHerds = 1;
    this.numberOfHerds = numberOfHerds;
    // initialize the herds and bands
    herd = new Herd[numberOfHerds];
    L = new Genome[numberOfHerds][];
    R = new Genome[numberOfHerds][];
    Lvitals = new int[numberOfHerds][];
    Rvitals = new int[numberOfHerds][];
    leave = new int[numberOfHerds];
    for (int h=0; h<numberOfHerds; ++h) {
      herd[h] = new Herd(initialPopulation, maximumPopulation, initialVitality);
      L[h] = new Genome[population];
      R[h] = new Genome[population];
      Lvitals[h] = new int[population];
      Rvitals[h] = new int[population];
    }
    stats = new Stats[numberOfHerds][];
    selectedHerd = 0;
    day = 0;
 } // Range constructor

  public void doSimulation(int lengthOfMatch,
                           int payoff[][], double mutationRate, 
                           double mutationSize, int thresholdVitality,
                           int maximumPopulation, double asexual) {
    day++;
    for (int h=0; h<numberOfHerds; ++h) {
      herd[h].runMatch(lengthOfMatch, payoff);
      // Now, remove some players due to death
      herd[h].death();
      // Next, some get born
      herd[h].birth(thresholdVitality, asexual);
      // Reduce to the maximum allowed population
      herd[h].reduce(maximumPopulation);
      // Finally, mutate some of them
      herd[h].mutate(mutationRate, mutationSize);
    } // for
  } // doSimulation


  public void migrate(int bandSize) {
    if (bandSize == 0) return;  // nobody's going anywhere
    // first bands leave the herds
    for (int h=0; h<numberOfHerds; ++h) {
      leave[h] = (herd[h].getPopulation()+1)/3;
      if (bandSize < leave[h])
        leave[h] = bandSize;
      herd[h].migrateOut(leave[h],L[h],Lvitals[h]);
      herd[h].migrateOut(leave[h],R[h],Rvitals[h]);
    }
    // next they join the neighboring herds
    for (int h=0; h<numberOfHerds; ++h) {
      herd[(h+numberOfHerds-1) % numberOfHerds].migrateIn(leave[h],L[h],Lvitals[h]);
      herd[(h+1) % numberOfHerds].migrateIn(leave[h],R[h],Rvitals[h]);
    }
  } // migrate

  public void graphUpdate (ColorGraph colorGraph) {
    if (herd == null) return; // herd not initialized
    colorGraph.newData(herd[selectedHerd].getGenomeColor(),
                       herd[selectedHerd].getPopulation());
  } // graphUpdate

  public void statUpdate() {
    for (int h=0; h<numberOfHerds; ++h)
      stats[h] = herd[h].getStats();
  } // statUpdate

  public void barGraphUpdate (BarGraph barGraph) {
    barGraph.setValues(stats[selectedHerd]);
  } // barGraphUpdate

} // Range.java


