import java.awt.*;

public class Genome {

  double firstMove;
  double leave[];
  double secondMove[][];
  double thirdMove[][][][];

  public Genome () {
    secondMove = new double[2][2];
    thirdMove = new double[2][2][2][2];
    leave = new double[2];
  }
  
  public void randomize() {
    firstMove = Math.random();
    for (int i=0; i<=1; ++i) {
      leave[i] = Math.random();
      for (int j=0; j<=1; ++j) {
        secondMove[i][j] = Math.random();
        for (int m=0; m<=1; ++m)
          for (int n=0; n<=1; ++n)
            thirdMove[i][j][m][n] = Math.random();
      }
    }
  } // randomize
  
  public Genome duplicate() {
    Genome other = new Genome();
    other.firstMove = firstMove;
    for (int i=0; i<=1; ++i)
      for (int j=0; j<=1; ++j) {
        other.secondMove[i][j] = secondMove[i][j];
        for (int m=0; m<=1; ++m)
          for (int n=0; n<=1; ++n)
            other.thirdMove[i][j][m][n] = thirdMove[i][j][m][n];
      }
    other.leave = leave;
    return other;
  } // clone
    
  public void mutate(double amount) {
    firstMove = adjust(firstMove,amount);
    for (int i=0; i<=1; ++i) {
      leave[i] = adjust(leave[i],amount);        
      for (int j=0; j<=1; ++j) {
        secondMove[i][j] = adjust(secondMove[i][j],amount);
        for (int m=0; m<=1; ++m)
          for (int n=0; n<=1; ++n)
            thirdMove[i][j][m][n] = adjust(thirdMove[i][j][m][n],amount);
      }
    }
  } // 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();
    third.firstMove = select(first.firstMove, second.firstMove);
    for (int i=0; i<=1; ++i) {
      third.leave[i] = select(first.leave[i],second.leave[i]);
      for (int j=0; j<=1; ++j) {
        third.secondMove[i][j] = select(first.secondMove[i][j],
                                 second.secondMove[i][j]);
        for (int m=0; m<=1; ++m)
          for (int n=0; n<=1; ++n)
            third.thirdMove[i][j][m][n] = select(first.thirdMove[i][j][m][n],
                                                 second.thirdMove[i][j][m][n]);
      }
    }
    return third;
  } // cross
  
  private static double select(double first, double second) {
    return (Math.random() < 0.5) ? first : second;
  }
       
  public String toString() {
   return
      digit(firstMove) +
      digit(leave[0]) +
      digit(leave[1]) +
      digit(secondMove[0][0]) +
      digit(secondMove[0][1]) +
      digit(secondMove[1][0]) +
      digit(secondMove[1][0]) +
      digit(thirdMove[0][0][0][0]) +
      digit(thirdMove[0][0][0][1]) +
      digit(thirdMove[0][0][1][0]) +
      digit(thirdMove[0][0][1][1]) +
      digit(thirdMove[0][1][0][0]) +
      digit(thirdMove[0][1][0][1]) +
      digit(thirdMove[0][1][1][0]) +
      digit(thirdMove[0][1][1][1]) +
      digit(thirdMove[1][0][0][0]) +
      digit(thirdMove[1][0][0][1]) +
      digit(thirdMove[1][0][1][0]) +
      digit(thirdMove[1][0][1][1]) +
      digit(thirdMove[1][1][0][0]) +
      digit(thirdMove[1][1][0][1]) +
      digit(thirdMove[1][1][1][0]) +
      digit(thirdMove[1][1][1][1]) ;
  }//toString

  private String digit(double prob) {
    return Integer.toString((int)(10.0*prob));
  }

  public Color toColor() {
      /* red = firstMove; // what do you do on your first move? */
      return new Color((float)firstMove,(float)leave[0],(float)leave[1]);
  } //tocolor

} // Genome

