package aigame;

import java.lang.String;
import java.lang.Object;
import java.math.*;
import java.io.*;
import java.util.Random;
import java.util.StringTokenizer;
import java.io.DataInputStream;

public class kernEval
{   /*public static void main(String[] args)
    {   int gameState[] = new int[4], i, mode;
        String temp;
        System.out.println("Enter mode: ");
        temp = getstr();
        mode = Integer.parseInt(temp);
        for(i=0; i<4; i++)
        {   System.out.print("Enter number: ");
            temp = getstr();
            gameState[i] = Integer.parseInt(temp);
        }

        gameState = kernRet(gameState, mode);
    }*/

    public static int[] kernRet(int[] gameState, int mode)
    {   String binEquiv[] = new String[4], XOR = "", GrAND = "", temp = "", flags = "";
        int i, j, count, modVal, dGrAND, row, tempMove[] = new int[3], strCount = 0;
        int recState[][] = new int[28][7], recIndex = 0, store[] = new int[4], winSt = 0;
        String moves = "3 2 0 4 -2 0 2 ;5 6 1 0 -1 1 3 ;4 4 1 2 1 3 2 ;";
        Random rand = new Random();
        StringTokenizer toke = new StringTokenizer(moves), salot = new StringTokenizer(GrAND);
        boolean flag = false, win = true;
        switch(mode)
        {   case 1:   gameState = easyMode(gameState);
                      break;
            case 2:   gameState = medDif(gameState);
                      break;
            case 3:   binEquiv = decToBin(gameState);
                      XOR = x_or(binEquiv);
                      gameState = getAnswer(XOR, binEquiv, gameState);
                      break;
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:   mode -= 3;
                      for(int a1=0; a1<4; a1++)
                          store[a1] = gameState[a1];
                      for(int k=0; k<(30*mode); k++)
                      {   toke = new StringTokenizer(moves);
                          salot = new StringTokenizer(GrAND);
                          flags = "";
                          recIndex = 0;
                          if(k < ((30*mode)-1))
                          {   for(int a1=0; a1<4; a1++)
                                  gameState[a1] = rand.nextInt(7);
                          }
                          else
                          {   gameState = store;
                              tempMove = KSystem(gameState, moves);
                              break;
                          }
                          while(flags.compareTo("0000") != 0)
                          {   flags = "";
                              tempMove = KSystem(gameState, moves);
                              for(int r=0; r<4; r++)
                              {   recState[recIndex][r] = gameState[r];
                              }
                              recState[recIndex][4] = 0;
                              recState[recIndex][5] = tempMove[0];
                              recState[recIndex][6] = tempMove[1];
                              recState[recIndex][tempMove[0]] += tempMove[1];
                              recIndex++;
                              for(int h=0; h<4; h++)
                                  flags += gameState[h];
                              if(flags.compareTo("0000")==0)
                                  win = true;
                              else
                              {   binEquiv = decToBin(gameState);
                                  XOR = x_or(binEquiv);
                                  gameState = getAnswer(XOR, binEquiv, gameState);

                              }
                              flags = "";
                              for(int h=0; h<4; h++)
                                  flags += gameState[h];
                              if(flags.compareTo("0000")==0)
                                  win = false;
                          }

                          for(int h=0; h<recIndex; h++)
                          {   if(win)
                                  recState[h][4] = 1;
                              else
                                  recState[h][4] = -1;
                              tempMove = getState(recState[h], moves);
                              if(tempMove[1] == 0)
                              {   for(int r=0; r<7; r++)
                                      moves += (recState[h][r] + " ");
                                  moves += ";";
                              }
                              else
                              {   salot = new StringTokenizer(moves, ";");
                                  GrAND = "";
                                  strCount = 0;
                                  for(int u=0; u<tempMove[2]; u++)
                                  {   GrAND = salot.nextToken(";");
                                      strCount += GrAND.length() + 1;
                                  }
                                  int g=0;
                                  toke = new StringTokenizer(GrAND);
                                  if((toke.countTokens() != 0)&&(toke.hasMoreTokens()))
                                  {   while(toke.hasMoreTokens())
                                      {   temp = toke.nextToken();
                                          if(g == 4)
                                              recState[h][4] = winSt;
                                          g++;
                                      }
                                  }
                                  int pos = strCount;
                                  while((pos < moves.length())&&(moves.charAt(pos) != ';'))
                                      pos++;
                                  pos++;
                                  temp = "";
                                  recState[h][4] += winSt;
                                  for(int u=0; u<7; u++)
                                  {    temp += (recState[h][u] + " ");
                                  }
                                  temp += ";";
                                  moves = (moves.substring(0, strCount) + temp + moves.substring(pos, moves.length()));
                              }
                          }
                      }
                      break;
        }

        return (gameState);
    }

    public static String[] decToBin(int[] gameState)
    {   String[] binEquiv = new String[4];
        int i, j, modVal;
        for(i=0; i<4; i++)
        {   binEquiv[i] = "";
            modVal = gameState[i];
            for(j=2; j>=0; j--)
            {   if((int)(modVal/Math.pow(2, j))==1)
                    binEquiv[i] += "1";
                else
                    binEquiv[i] += "0";
                modVal = modVal % (int)Math.pow(2,j);
            }
        }
        return (binEquiv);
    }

    public static String x_or(String[] binEquiv)
    {   String XOR = "";
        int i, j, count;
        for(i=0; i<3; i++)
        {   count = 0;
            for(j=0; j<4; j++)
            {   if(binEquiv[j].charAt(i) == '1')
                    count += 1;
            }
            XOR += (count % 2);
        }
        return (XOR);
    }

    public static int[] getAnswer(String XOR, String[] binEquiv, int[] gameState)
    {   String GrAND = "", temp = "", ret = "";
        int dGrAND = 0, row = 0, count=0, i, j, finSt = -1, modVal=0;
        boolean flag = false, xor = true;
        int answer[] = new int[2];
        for(i=0; i<4; i++)
        {   count = -1;
            temp = "";
            for(j=0; j<3; j++)
            {   if((binEquiv[i].charAt(j) == '1')&&(XOR.charAt(j) == '1'))
                    temp += "1";
                else
                    temp += "0";
            }
            count = binToDec(temp);
            if(count > dGrAND)
            {   GrAND = temp;
                dGrAND = count;
                row = gameState[i];
                modVal = i;
            }
        }
        if(XOR.compareTo("000") == 0)
            gameState = easyMode(gameState);
        else
            xor = false;
        binEquiv[modVal] = "000";
        XOR = x_or(binEquiv);
        for(int w=0; w<4; w++)
        {   ret += gameState[w];
            if((gameState[w] != 0)&&(finSt == -1))
            {    finSt = w;
                flag = true;
            }
            else if((gameState[w] != 0)&&(finSt != -1))
                flag = false;
        }
        if(flag)
        {   gameState[finSt] = 0;
            return (gameState);
        }
        if(ret.compareTo("0000") == 0)
            return (gameState);
        if(!xor)
        {   count = binToDec(XOR);
            count = (gameState[modVal] - count);
            gameState[modVal] -= count;
        }
        return (gameState);

    }

    public static int binToDec(String temp)
    {   int modVal=0, i, j, count = 0;
        for(j=2; j>=0; j--)
        {   if(temp.charAt(j) == '1')
                count += (int)Math.pow(2,modVal);
            modVal++;
        }
        return (count);
    }

    public static int[] medDif(int[] gameState)
    {   int big=0, next=0, i, flags=0, temp=0, small=-1;
        boolean flag = false;
        Random rand = new Random();
        for(i=0;i<4;i++)
        {   if(gameState[i] == 0)
            {   flag = true;
                flags = i;
            }
            if(gameState[i] > gameState[big])
                big = i;
        }
        for(i=0;i<4;i++)
        {   if((big != i)&&(gameState[i] > temp))
            {   next = i;
                temp = gameState[next];
            }
            if((flag)&&(big!=i)&&(next!=i)&&(gameState[i] != 0))
                small = i;
        }
        if((small == -1)&&(gameState[big] != gameState[next]))
            gameState[big] = gameState[next];
        else if(gameState[big] == gameState[next])
            gameState = easyMode(gameState);
        else if(gameState[big] == gameState[next] + gameState[small])
            gameState = easyMode(gameState);
        else if(gameState[next] == 0)
            gameState[big] = 0;
        else
        {   if(flag)
                gameState[small] = (gameState[big] - gameState[next]);
            else
            {   flags = rand.nextInt(4);
                while(gameState[flags] == 0)
                    flags = rand.nextInt(4);
                gameState[flags] = 0;
            }
        }
        return (gameState);
    }

    public static int[] easyMode(int[] gameState)
    {   Random rand = new Random();
        int randRow=0, randCol=0;
        while(gameState[randRow] == 0)
            randRow = rand.nextInt(4);
        while(randCol == 0)
            randCol = rand.nextInt(gameState[randRow]+1);
        gameState[randRow] -= randCol;
        return (gameState);
    }

    public static int[] KSystem(int[] gameState, String moves)
    {   int recStates[] = new int[3], tempState[] = new int[4];
        recStates = getState(gameState, moves);
        if(recStates[1] != 0)
            gameState[recStates[0]] -= recStates[1];
        if(recStates[1] == 0)
        {   for(int Store = 0; Store<4; Store++)
                tempState[Store] = gameState[Store];
            gameState = easyMode(gameState);
            for(int k=0; k<4; k++)
            {   if(tempState[k] != gameState[k])
                {   recStates[0] = k;
                    recStates[1] = tempState[k] - gameState[k];
                }
            }

        }
        return (recStates);
    }

    public static int[] getState(int[] gameState, String moves)
    {   StringTokenizer toke, salot = new StringTokenizer(moves, ";");
        String tempIn, gameStr = "", fileApp, moveStr;
        int i, tempState[] = new int[7], flagArr[] = new int[4], tokeCount = 0;
        int[] recStates = new int[3], tempStore = new int[7];
        Random rand = new Random();
        for(int l=0; l<7; l++)
            tempStore[l] = 0;
        tempStore[4] = -4;
        boolean flag = true, moveThere = false;
        while((salot.hasMoreTokens()))
        {   tempIn = salot.nextToken();
            toke = new StringTokenizer(tempIn);
            i = 0;
            while((toke.hasMoreTokens())&&(i<7))
            {   tempState[i] = Integer.parseInt(toke.nextToken());
                i++;
            }
            for(int l=0; l<4; l++)
                flagArr[l] = -1;
            for(int j=0; j<4; j++)
            {   for(int k=0; k<4; k++)
                {   if((flagArr[k] == -1)&&(gameState[j] == tempState[k]))
                    {   flagArr[k] = j;
                    }
                }
            }
            flag = true;
            for(int j=0; j<4; j++)
                flag = ((flag)&&(flagArr[j] != -1));
            if((flag)&&(tempState[4] > -4))
            {   moveThere = true;
                if(tempStore[4] <= tempState[4])
                {   if((tempStore[4] == tempState[4])&&(rand.nextBoolean())&&(tempStore[0] != 0))
                    {   for(int z=0; z<7; z++)
                            tempStore[z] = tempState[z];
                    }
                    else
                    {   for(int z=0; z<7; z++)
                            tempStore[z] = tempState[z];
                    }
                }
                recStates[2] = tokeCount;
            }
            else
                moveThere = (moveThere && false);
            tokeCount++;
        }
        for(int z=0; z<7; z++)
            tempState[z] = tempStore[z];
        if(moveThere)
        {   for(int q=0; q<4; q++)
            {   if(gameState[q] == tempState[tempState[5]])
                {   recStates[0] = q;
                    recStates[1] = tempState[6];
                }
            }
            return (recStates);
        }
        else
        {   recStates[0] = recStates[1] = 0;
            recStates[2] = 0;
            return (recStates);
        }
    }
}






