import java.awt.Color;

public class Genome {

  private double gene[];
  private int pop;             // The number of players with this strategy

  public static final int length = 23;

  // Moves are either "cooperate" ("nice") or "defect" ("nasty")
  public static final int COOPERATE = 0;
  public static final int DEFECT = 1;

  public Genome() {
    gene = new double[length];
    pop = 0;
  }

  public void resetPopulation() { pop = 0; }
  
  public void incrementPopulation() { pop++; }
  
  public void decrementPopulation() { pop--; }

  public int firstMove() {
    return (Math.random() > gene[0]) ? 0 : 1;
  }

  public boolean leave (int myLastPlay, int otherLastPlay) {
    return (Math.random() > gene[1 + otherLastPlay])? false : true;
  }

  public int secondMove (int myLastPlay, int otherLastPlay, int currentScore) {
    return (Math.random() >  gene[3 + 2*myLastPlay + otherLastPlay]) ? 0 : 1;
  }

  public int thirdMove  (int myLastPlay, int otherLastPlay,
                         int myPreviousPlay, int otherPreviousPlay, int currentScore) {
    return (Math.random() > gene[7 + 8*myLastPlay + 4*otherLastPlay +
                            2*myPreviousPlay + otherPreviousPlay]) ? 0 : 1;
  }

  public void randomize() {
    for (int i=0; i<length; ++i)
      gene[i] = Math.random();
  } // randomize

  public Genome duplicate() {
    Genome other = new Genome();
    for (int i=0; i<length; ++i)
        other.gene[i] = gene[i];
    return other;
   } // duplicate

  public Genome mutate(double amount) {
    Genome mut = new Genome();
    for (int i=0; i<length; ++i)
      mut.gene[i] = adjust(gene[i],amount);
    return mut;
  } // mutate

  private static double adjust(double value, double mutationAmount) {
    double newValue = value + mutationAmount*2.0*Math.random() - mutationAmount;
    if (newValue < 0.0)
      newValue = 0.0;
    else if (newValue > 1.0)
      newValue = 1.0;
    return newValue;
  } // adjust

  

  public static Genome cross(Genome first, Genome second) {
    Genome third = new Genome();
    for (int i=0; i<length; ++i)
      third.gene[i] = (Math.random() < 0.5)? first.gene[i] : second.gene[i];
    return third;
  } // cross


  public String toString() {
    String s = "";
    for (int i=0; i<length; ++i)
      s = s+digit(gene[i]);
    return s;
  } // toString

  private String digit(double prob) {
    if (prob == 1.0)
      return "*";
    else
      return Integer.toString((int)(10.0*prob));
  }

  public Color toColor() {
    return new Color((float)gene[0],(float)gene[1],(float)gene[2]);
  } //toColor
  
  
  public static Stats[] getStats(Player P[]) {
    Stats stats[] = new Stats[length];
    int n = P.length;
    for (int i=0; i<length; ++i) {
      stats[i] = new Stats();
      double sum = 0.0;
      double sumOfSquares = 0.0;
      for (int j=0; j<n; ++j) {
        double value = P[j].G.gene[i];
        sum += value;
        sumOfSquares += value*value;
      } // for j
      if (n > 0)
        stats[i].mean = sum/n;
      else
        stats[i].mean = 0.0;
      if (n > 1)
        stats[i].standardDeviation = Math.sqrt((sumOfSquares-sum*stats[i].mean)/(n-1));
      else
        stats[i].standardDeviation = 0.0;
    } // for i
    return stats;
  } // getStats

} // Genome

