import java.applet.*;
import java.awt.*;
import java.util.*;

public class MMindHint extends Applet {
  public void init() {
    // initialize variables
    count=10;
    iData=new int[4][count];
    gdata=new boolean[6][6][6][6];
    data=new Label[count];
    a=new Label[count];
    b=new Label[count];
    iA=new int[count];
    iB=new int[count];

    // set layout
    setLayout(new GridLayout(count+1,1));
    FlowLayout f=new FlowLayout();
    Panel p;
    entry=new TextField("",4);
    p=new Panel();
    p.setLayout(f);
    p.add(entry);
    grade1=new TextField("",1);
    grade2=new TextField("",1);
    p.add(grade1);
    p.add(grade2);
    sButton=new Button("Restart");
    p.add(sButton);
    add(p);

    // add components
    for(int i=0;i<count;i++) {
      data[i]=new Label();
      a[i]=new Label();
      b[i]=new Label();
      p=new Panel();
      p.setLayout(f);
      add(p);
      p.add(data[i]);
      p.add(a[i]);
      p.add(b[i]);
    }

    begin();
  }

  void begin() {
    // reset guess grid so all guesses are possible
    for(int i1=0;i1<6;i1++)
      for(int i2=0;i2<6;i2++)
        for(int i3=0;i3<6;i3++)
          for(int i4=0;i4<6;i4++) 
            gdata[i1][i2][i3][i4]=true;            

    turn=0;
    won=false;
    // clear out guess display
    for(int i=0;i<count;i++) {
      data[i].setText("      ");
      a[i].setText("   ");
      b[i].setText("   ");
    }
    entry.setText("");
    grade1.setText("");
    grade1.setText("");
  }
    
  public boolean action(Event e,Object o) {
    if(e.target instanceof Button) {
      begin();
      return true;
    }
    return super.action(e,o);
  }

  public boolean handleEvent(Event e) {
    if(e.id==Event.KEY_RELEASE && e.target instanceof TextField
        && e.key==10) {    // enter key pressed
      if(won)
        entry.setText("Won!");
      else if(turn<count) {
        data[turn].setText(entry.getText());
        a[turn].setText(grade1.getText());
        b[turn].setText(grade2.getText());
        entry.setText("");
        grade1.setText("");
        grade2.setText("");
        process();
        turn++;
      }
      else  {
        entry.setText("Lost!");
        grade1.setText("");
        grade2.setText("");
      }
      return true;
    }

    return super.handleEvent(e);
  }

  void process() {
    int value=(int)sToF(data[turn].getText());
    int aa=(int)sToF(a[turn].getText());
    int bb=(int)sToF(b[turn].getText());
    int aCode[]=new int[4];

    for(int i=3;i>-1;i--) {
      aCode[i]=value%10-1;
      value=value/10;

      // store guess for hints
      iData[i][turn]=aCode[i];
    }

    iA[turn]=aa;
    iB[turn]=bb;

    if(aa==4) {
      won=true;
      entry.setText("Won!");
    }
    else {
      guess();
    }
  }

  void guess() {
    int aCode[]=new int[4];
    boolean found=false;

    for(int i=0;i<4;i++)
      aCode[i]=iData[i][turn];

    while(!found) {
      gdata[aCode[0]][aCode[1]]
        [aCode[2]][aCode[3]]=false;
      getNextGuess(aCode);
      found=tryGuess(aCode);
    }
    String s=new String();
    for(int i=0;i<4;i++) {
      s=s+Integer.toString(aCode[i]+1);
    }
    entry.setText(s);
    print("Guess",aCode);
  }

  void print(String label,int aCode[]) {
    System.out.print(label+":");
    for(int i=0;i<4;i++) {
      System.out.print(aCode[i]+1);
    }
    System.out.println();
  }

  void getNextGuess(int aCode[]) {
    int i=0;
    boolean found=false;
    while(!found){
      for(aCode[i]++;aCode[i]==6;aCode[i]++) {
        i++;
        for(int j=0;j<i;j++) {
          aCode[j]=0;
        }
        if(i==4) {
          i=0;
          aCode[i]--;
        }
      }
      found=gdata[aCode[0]][aCode[1]][aCode[2]]
           [aCode[3]];
    }
  }

  boolean tryGuess(int aCode[]) {
    int bCode[]=new int[4];
    int cCode[]=new int[4];
    int aa=0;
    int bb=0;

    for(int t=0;t<=turn;t++) {
      // get expendable copies
      aa=iA[t];
      bb=iB[t];
      for(int i=0;i<4;i++) {
        bCode[i]=aCode[i];
        cCode[i]=iData[i][t];
        // compare exact
        if(bCode[i]==cCode[i]) {
          aa--;
          if(aa<0)
            return false;
          bCode[i]=-1;
          cCode[i]=-2;
        }
      }
      if(aa!=0)
        return false;

      // compare right values
      for(int i=0;i<4;i++) {
        for(int j=0;j<4;j++) {
          if(bCode[i]==cCode[j]) {
            bb--;
            if(bb<0)
              return false;
            bCode[i]=-1;
            cCode[j]=-2;
          }
        }
      }
      if(bb!=0)
        return false;
    }
    return true;
  }

  float sToF(String s) {
    try {
      return Float.valueOf(s).floatValue();
    }
    catch(Exception e) {
      return 0;
    }
  }


  private Label data[];
  private int iData[][];
  private Label a[];
  private int iA[];
  private int iB[];
  private Label b[];
  private boolean gdata[][][][];
  private int count;
  private int turn;
  private TextField entry;
  private boolean won;
  private Button sButton;
  private TextField grade1;
  private TextField grade2;
}