/*----------------------------------------------------------------------+
|	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/home.html                     |
|        djoyce@clarku.edu                                              |
|                                                                       |
|	Date:	February, 2001.                                         |
+----------------------------------------------------------------------*/

import java.awt.event.*;
import java.awt.Color;

public class Range extends Thread {

  // constants
  final int max_n_herds = 200;
  
  // parameters
 
  int cost;              // cost to altruist in 10ths of a unit
  int benefit;           // benefit from altruist in 10ths of a unit
  int herd_size;         // each herd has this population
  int init_alt;          // how many initial altruists
  int n_herds;           // the number of herds
  int deaths;            // this many die and are born each day in each herd
  int max_days;          // how many days to run the simulation
  int band_size;         // each migrating band has this size
  int migration_period;  // how many days between migrations
  int timeout;           // milliseconds between days

  // herds are arranged in a circle.  Each migration period a band leaves
  // each to go to its two neighbors
  Herd H[];              // the herds
  Herd L[];              // the left moving bands
  Herd R[];              // the right moving bands

  int day;
  
  Moth V;
  RangeDisplay display;
  TimeGraph totStats;
  TimeGraph indivStats;


  boolean running = false;

  Range (Moth V_init) {
    V = V_init;
    H = new Herd[max_n_herds];
    L = new Herd[max_n_herds];
    R = new Herd[max_n_herds];
  }
  
  void reset(int cost_init, int benefit_init, int hs_init, int ia_init,
             int nh_init, int deaths_init, int md_init, int bs_init,
             int mp_init, int timeout_init) {
    cost = cost_init;
    benefit = benefit_init;
    herd_size = hs_init;
    init_alt = ia_init;
    n_herds = nh_init;
    deaths = deaths_init;
    max_days = md_init;
    band_size = bs_init;
    migration_period = mp_init;
    timeout = timeout_init;
    resetHerds();
  }

  void addStats(TimeGraph ts, TimeGraph is) {
    totStats = ts;
    indivStats = is;
  }

  public String toString() {
    String S = "n_herds="+n_herds;
    for (int i=0; i<n_herds; ++i)
      S += "\n "+ H[i].toString();
    return S;
  }

  void resetHerds() {
    day = 1;
    // initialize the herds and bands
    for (int i=0; i<n_herds; ++i) {
      if (i==0 || band_size == 0 || migration_period == 0) 
        H[i] = new Herd(0,init_alt,herd_size-init_alt);
      else
        H[i] = new Herd(0,0,herd_size);
      L[i] = new Herd(0,0,0);
      R[i] = new Herd(0,0,0);
    }
  }

  public void run() {
    int status = 0;
    while (true) {
      if (!running) 
        try {Thread.currentThread().sleep(100);}
          catch (InterruptedException e){}      
      else {
        if (timeout !=0) 
        try {Thread.currentThread().sleep(timeout);}
          catch (InterruptedException e){}
        else if (day % 10 == 0)
          try {Thread.currentThread().sleep(1);}
            catch (InterruptedException e){}
        next_day();
        status = report();
        if (status != 0) {
          running = false;
          if (status == 1) 
            V.play(V.getDocumentBase(), "that.hurts.au");
          else
            V.play(V.getDocumentBase(), "tiptoe.thru.the.tulips.au");
        }
      }
      display.repaint();
    }
  }
  
  void next_day() {
    for (int j=0; j<n_herds; ++j) {
      H[j].pairing();       // the animals pair off at the beginning of the day
      // a certain number are born based on vitality
      H[j].birth(cost/10.0, benefit/10.0, deaths);
      H[j].death(deaths);   // a same number die at random
    }
    if (migration_period != 0
        && band_size != 0
        && day % migration_period == 0)
      migrate();
     ++day;
  }

  void migrate() {
    // first bands leave the herds
    for (int i=0; i<n_herds; ++i) {
      H[i].migrate_out(band_size,L[i]);
      H[i].migrate_out(band_size,R[i]);
    }
    // next they join the neighboring herds
    for (int i=0; i<n_herds; ++i) {
      H[(i+n_herds-1) % n_herds].migrate_in(L[i]);
      H[(i+1) % n_herds].migrate_in(R[i]);
    }
  }
  
  int selected_herd = 0;
  
  int report() {
    int tot_paired = 0;
    int tot_unpaired = 0;
    int tot_selfish = 0;
    for (int  j=0; j<n_herds; ++j) {
      tot_paired   += H[j].paired;
      tot_unpaired += H[j].unpaired;
      tot_selfish  += H[j].selfish;
    }
    totStats.newData(tot_paired,
                     tot_unpaired,
                     tot_selfish,
                     Color.white,
                     Herd.chooseColor(tot_paired,tot_unpaired,tot_selfish),
                     Color.black);
    indivStats.newData(H[selected_herd].paired,
                       H[selected_herd].unpaired,
                       H[selected_herd].selfish,
                       Color.white,
                       H[selected_herd].chooseColor(),
                       Color.black);
    if (tot_paired + tot_unpaired == 0)
      return 1;
    else if (tot_selfish == 0)
      return 2;
    else
      return 0;
  }

}

