
//***********************************************************
//*
//* File:           Group1Player1.java
//* Author:         Edan, Lyuba, Andy
//* Contact:        lg532@columbia.edu
//* Update:         10.26.2003
//*
//***********************************************************

package Cluedo.g4;

import Cluedo.*;
import Cluedo.g4.IntegerList;
import ui.*;
import java.util.*;
import java.io.*;
import java.awt.Color;

public final class Group4Player1 implements IFCPlayer {
	
	Cluedo engine;
	static final String NAME = "The Red Herring";
	static final Color COLOR = new Color(1.0f,1.0f,0.0f);
    int shouldStartChecking = 0;
    int numTimesMatched = 0;


	int	   numCards;
	int    numCardsPerPlayer;
	int    numHiddenCards;
	int    numPlayers;
	int myIndex;

	Player []players;
	Card[] cards;
	int []myCards;
	int hiddenCardsFound;
    int turn=0;
    double[][] cardsAsked;
    double[][] cardsQuest;
    double[] cardsMultiplied;
    double[] cardsMultiplied2;
    double[] cardsSummed;
    int totalCardsEliminated;
    int[] holmesArray;
    int[] watsonArray;
    int[] lestradeArray;

    int nextInterrogatee = 0;

    public void register(Cluedo noclue) throws Exception {
    try
    {
	engine = noclue;
	
	numCards = noclue.numCards();
	numCardsPerPlayer = noclue.numCardsPerPlayer();
	numHiddenCards = noclue.numHiddenCards();
	numPlayers = noclue.numPlayers();
	myIndex = engine.indexOf(this);
	
	players = new Player[numPlayers + 1];
	for(int i = 0; i < numPlayers + 1; i++)
	    {
		players[i] = new Player(engine, i);
	    }
	
	cards = new Card[numCards + 1];
	for(int i = 0; i <= numCards; i++)
	    {
		cards[i] = new Card(i, numPlayers, numCardsPerPlayer, numHiddenCards);
	    }

	cardsAsked = new double[numCards + 1][numPlayers];
	cardsQuest = new double[numCards + 1][numPlayers];
	cardsMultiplied = new double[numCards + 1];
	cardsMultiplied2 = new double[numCards + 1];
	cardsSummed = new double[numCards + 1];
	for (int i = 0; i<=numCards; i++) {
	    cardsMultiplied[i]=1;
	    cardsMultiplied2[i]=1;
	    cardsSummed[i]=0;
	    for (int j=0; j<numPlayers; j++) {
		cardsAsked[i][j] = 1;
		cardsQuest[i][j] = 1;
	    }
	}


	holmesArray = new int[numHiddenCards];
	watsonArray = new int[numHiddenCards];
	lestradeArray = new int[numHiddenCards];

	//System.out.println("5");
	myCards = new int[numCardsPerPlayer];
	myCards = noclue.getPlayerList(myIndex, this);
	
	//System.err.println("me: " + myIndex);
	//System.out.println("6");
	for(int i = 0; i < myCards.length; i++)	
	    {		
			//System.out.println("I HAVE A CARD NUMBERED "+myCards[i]);
			playerHasCard(myCards[i], myIndex);
	    }
	
	for(int i = 0; i < myCards.length; i++)
	    {
		cards[myCards[i]].playerHolding = myIndex;	
		cards[myCards[i]].isHiddenCard = false;			
	    }
	
	hiddenCardsFound = 0;
    }
	catch(Exception e)
	{
	    //System.out.println("Error in register.");
		handleException(e);
	}
    }
    

    public Move move() throws Exception {
	try {    
	    //deductions();


	    for (int i=1;i<=numCards;i++){
		for (int j=0; j<numPlayers; j++) {
		    cardsAsked[i][j]=((cardsAsked[i][j])/2);
		    cardsQuest[i][j]=((cardsQuest[i][j])/2);
		}
	    }

	    int round = engine.currRound() - 1;
            if(round >= 0) //history empty at round 0
		{
		    
		    MoveResult lastMove = engine.history(round);
		    //fill in data based on history
		    while(lastMove != null && lastMove.player != myIndex)
			{ 
			    Player player = players[lastMove.player];
			    Player interrogatee = players[lastMove.interrogatee];
				
				//guesses are handled in playerexited()
				//interrogation
			    if(lastMove.type == 'i')
				{
				    //the interogatee answered
				    if(lastMove.response)
					{
					    IntegerList disjunction = new IntegerList(lastMove.cardlist.length);
					    for(int k = 0; k < lastMove.cardlist.length; k++)
						{
						    int minicard = lastMove.cardlist[k];
						    //System.out.println("Over here");
						    disjunction.addInteger(lastMove.cardlist[k]); 
						    //System.out.println("Card"+lastMove.cardlist[k]);
						    cardsAsked[minicard][lastMove.player]=cardsAsked[lastMove.cardlist[k]][lastMove.player]+2;
						    cardsQuest[minicard][lastMove.interrogatee]=cardsQuest[lastMove.cardlist[k]][lastMove.interrogatee]+2;
						    

						    //System.out.println("Over there");
						}
					    
					    for(int k = 0; k < disjunction.size(); k++)
						{
						   //System.err.print(disjunction.getInteger(k) + " ");
						}
					    
					    disjunction = simplifyDisjunction(disjunction, lastMove.interrogatee);
					    if(disjunction.size() == 1)
						{
						    playerHasCard( disjunction.getInteger(0), lastMove.interrogatee);
						    //interrogatee.addHasCard(disjunction.getInteger(0), cards, players);
						}
					    else
						interrogatee.addDisjunction(disjunction);
					    inferencesAndDeductions();
					    
					}
				    
				    //no answer
				    else
					{
					    for(int k = 0; k < lastMove.cardlist.length; k++) {
						playerDoesNotHaveCard(lastMove.cardlist[k], lastMove.interrogatee);
						cardsAsked[lastMove.cardlist[k]][lastMove.player]=cardsAsked[lastMove.cardlist[k]][lastMove.player]+3;
						cardsQuest[lastMove.cardlist[k]][lastMove.interrogatee]=cardsQuest[lastMove.cardlist[k]][lastMove.interrogatee]+3;
						inferencesAndDeductions();
					    }
					} 
				    
				}
				
			    round--;
			    if(round >= 0)
	    			lastMove = engine.history(round);	  
			    else lastMove = null;
			    //deductions();
			}
		}
	    
	    if (players[numPlayers].solved() || players[numPlayers].numCardsLeftToFind() == 0) {
		//System.out.println("Guessing Now");
		int[] asklist = new int[numHiddenCards];
		//System.out.println("...");
		int next = 0;
		for(int i = 1; i < (numCards + 1); i++)
		    {
			//System.out.println(i);
			if(players[numPlayers].hasCard(i))
			    {
				//System.out.println("Guessing " + i);
				asklist[next] = i;
				next++;
			    }
		    }
		return new Move(_CGUESS, asklist);
	    }
	    turn++;

		
	    if (false&&(turn > 10) && (players[numPlayers].numCardsLeftToFind() > (numHiddenCards + numPlayers))) {
		double Highest=0;
		for (int i=1; i <= numCards; i++) {
		    cardsMultiplied[i]=1;
		}
		

		for (int i=1; i <= numCards; i++) {
		    for (int j = 1; j<numPlayers; j++) {
			cardsMultiplied[i] = cardsMultiplied[i]*cardsAsked[i][j];
			//cardsMultiplied[i] = cardsMultiplied[i]*cardsQuest[i][j];
			
		    }
		}
		for (int i=1; i <= numCards; i++) {
		    if (cardsMultiplied[i]>Highest) {
			Highest=cardsMultiplied[i];
		    }
		}
		double Highlimit=0;
		int currentLowest=-1;
		int numGoneThrough=0;
		double LowsestPosNum=0; 
		for (int i=1; i <= numCards; i++) {
		    if (!(cards[i].hasPlayer(numPlayers) || cards[i].doesNotHavePlayer(numPlayers))) {			
			if (numGoneThrough == 0){
			    currentLowest=i;
			    Highlimit=cardsMultiplied[i];
			}
			else if (cardsMultiplied[i] < Highlimit) {
			    currentLowest=i;
			    Highlimit=cardsMultiplied[i];
			}
		    }
		}
		//		System.out.println ("Edan! "+cardsMultiplied[currentLowest]);
		if ((currentLowest > 0) && (cardsMultiplied[currentLowest]<Highest)) {
		    players[numPlayers].addDoesNotHave(currentLowest, cards, players);
		}
		deductions();
		}
	    



	    /*
	    if (turn>5) {
		double numberCardsKnown=0;
		double limitNum;
		double currentLargestNum = 0;
		int currentplacement=0;
		int[] currentList = new int[numHiddenCards];
		//System.out.println("Going to try to guess");
		for (int i = 0; i<=numCards; i++) {
		   // System.out.println(i);
		    cardsMultiplied[i]=1; 
		}
		for (int i=1; i<=numCards; i++) {
		    if (cards[i].solved()) {
			numberCardsKnown++;
		    }
		}
		//System.out.println("EdanState Turn "+turn+" with "+numberCardsKnown+" cards known");
		
		for (int i=1; i <= numCards; i++) {
		  //  System.out.println("i is "+i);
		    for (int j = 1; j<numPlayers; j++) {
			//System.out.println("j is "+j);
			cardsMultiplied[i] = cardsMultiplied[i]*cardsAsked[i][j];
			cardsMultiplied2[i] = cardsMultiplied2[i]*cardsQuest[i][j];
			
		    }
		    cardsSummed[i]=cardsMultiplied[i]*cardsMultiplied2[i];
		    if (cardsSummed[i]<1) {
			cardsSummed[i]=1;
		    }
		}
		

		for (int i=1; i <= numCards; i++) {
		    if (cards[i].hasPlayer(numPlayers)){
			currentList[currentplacement] = i;
			currentplacement++;
			cardsSummed[i] = -1;
		    }  // Put in Cards you know are hidden.
		    else if (cards[i].doesNotHavePlayer(numPlayers)) {
			cardsSummed[i] = -1;
		    }
		    else {
			if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum=cardsSummed[i];
			    
			}
		    }  // make a note of the most likeliest number;
		}
		limitNum=currentLargestNum;
		currentLargestNum=0;
		
		while (currentplacement < (numHiddenCards)) {
		    //System.out.println("limitNum "+limitNum);
		    //System.out.println ("Guessing: got "+currentplacement+" cards so far");
		    for (int i=1; i <= numCards; i++) {
			//System.out.println (i);
			if (cardsSummed[i]==(limitNum)) {
			    if (currentplacement < (numHiddenCards)) {
			      //  System.out.println("EdanState for turn "+turn+" is "+i);
				currentplacement++;
				cardsSummed[i]=-1;
				//System.out.println("Here");
			    }
			}
			else if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum = cardsSummed[i];
			    
			   }
			   }
			   limitNum=currentLargestNum;
			   currentLargestNum=0;
			   }}
	    */
		
		
	    if (turn> ((numCardsPerPlayer * (numPlayers - 1))/2)) { //CardsAsked only
		double numberCardsKnown=0;
		double limitNum;
		double currentLargestNum = 0;
		int currentplacement=0;
		int[] currentList = new int[numHiddenCards];
		//System.out.println("Going to try to guess");
		for (int i = 0; i<=numCards; i++) {
		    //System.out.println(i);
		    cardsMultiplied[i]=1; 
		}
		for (int i=1; i<=numCards; i++) {
		    if (cards[i].solved()) {
			numberCardsKnown++;
		    }
		}
		//System.out.println("EdanState Turn "+turn+" with "+numberCardsKnown+" cards known");
		
		for (int i=1; i <= numCards; i++) {
		    //System.out.println("i is "+i);
		    for (int j = 1; j<numPlayers; j++) {
			//System.out.println("j is "+j);
			cardsMultiplied[i] = cardsMultiplied[i]*cardsAsked[i][j];
			
		    }
		    cardsSummed[i]=cardsMultiplied[i];
		    if (cardsSummed[i]<1) {
			cardsSummed[i]=1;
		    }
		}
		
		
		for (int i=1; i <= numCards; i++) {
		    if (cards[i].hasPlayer(numPlayers)){
			watsonArray[currentplacement] = i;
			//System.out.println("Watson adds "+i);
			currentplacement++;
			cardsSummed[i] = -1;
		    }  // Put in Cards you know are hidden.
		    else if (cards[i].doesNotHavePlayer(numPlayers)) {
			cardsSummed[i] = -1;
		    }
		    else {
			if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum=cardsSummed[i];
			    
			}
		    }  // make a note of the most likeliest number;
		    }
		limitNum=currentLargestNum;
		currentLargestNum=0;
		
		while (currentplacement < (numHiddenCards)) {
		    //System.out.println("limitNum "+limitNum);
		    //System.out.println ("Guessing: got "+currentplacement+" cards so far");
		    for (int i=1; i <= numCards; i++) {
			//System.out.println (i);
			if (cardsSummed[i]==(limitNum)) {
			    if (currentplacement < (numHiddenCards)) {
				//     System.out.println("EdanState Asked for turn "+turn+" is "+i+" with "+cardsSummed[i]);
				watsonArray[currentplacement]=i;
				currentplacement++;
				cardsSummed[i]=-1;
				//System.out.println("Here");
			    }
			}
			else if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum = cardsSummed[i];
			    
			}
		    }
		    limitNum=currentLargestNum;
		    currentLargestNum=0;
		}
	    }

	    if (turn> ((numCardsPerPlayer * (numPlayers - 1))/2)) { // Quest only
		double numberCardsKnown=0;
		double limitNum;
		double currentLargestNum = 0;
		int currentplacement=0;
		int[] currentList = new int[numHiddenCards];
		//System.out.println("Going to try to guess");
		for (int i = 0; i<=numCards; i++) {
		    //System.out.println(i);
		    cardsMultiplied[i]=1; 
		}
		for (int i=1; i<=numCards; i++) {
		    if (cards[i].solved()) {
			numberCardsKnown++;
		    }
		}
		//System.out.println("EdanState Turn "+turn+" with "+numberCardsKnown+" cards known");
		
		for (int i=1; i <= numCards; i++) {
		    //System.out.println("i is "+i);
		    for (int j = 1; j<numPlayers; j++) {
			//System.out.println("j is "+j);
			//System.out.println("CardQuest output "+i+","+j+" "+cardsQuest[i][j]);
			cardsMultiplied2[i] = cardsMultiplied2[i]*cardsQuest[i][j];
			
		    }
		    cardsSummed[i]=cardsMultiplied2[i];
		}
		
		
		for (int i=1; i <= numCards; i++) {
		    //System.out.println("cardSummed for "+i+" is "+cardsSummed[i]);
		    if (cards[i].hasPlayer(numPlayers)){
			holmesArray[currentplacement] = i;
			currentplacement++;
			cardsSummed[i] = -1;
		    }  // Put in Cards you know are hidden.
		    else if (cards[i].doesNotHavePlayer(numPlayers)) {
			cardsSummed[i] = -1;
		    }
		    else {
			if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum=cardsSummed[i];
			    
			}
		    }  // make a note of the most likeliest number;
		    }
		limitNum=currentLargestNum;
		currentLargestNum=0;
		
		while (currentplacement < (numHiddenCards)) {
		    //System.out.println("limitNum "+limitNum);
		    //System.out.println ("Guessing: got "+currentplacement+" cards so far");
		    for (int i=1; i <= numCards; i++) {
			//System.out.println (i);
			if (cardsSummed[i]==(limitNum)) {
			    if (currentplacement < (numHiddenCards)) {
			        //System.out.println("EdanState Questioned for turn "+turn+" is "+i+" with "+cardsSummed[i]);
				holmesArray[currentplacement]=i;
				currentplacement++;
				cardsSummed[i]=-1;
				//System.out.println("Here");
			    }
			}
			else if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum = cardsSummed[i];
			    
			}
		    }
		    limitNum=currentLargestNum;
		    currentLargestNum=0;
		}
	    }



	    // Check to see if Holmes and Watson are on the same page.

	    if (turn>(((numCardsPerPlayer * (numPlayers - 1))*1)/2)) {
		boolean matchedOne=false;
		boolean matchedArray=true;
		int totalMatched=0;

		/*//System.out.println("Holmes and Watson");
		for (int i=0; i<numHiddenCards; i++) {
		   // System.out.println("Holmes = "+holmesArray[i]+" Watson "+watsonArray[i]);
		    }*/


		matchedArray=compareArrays(watsonArray, holmesArray);


		if (matchedArray) {  
		    // System.out.println("Holmes and Watson matched");
		    // This checks if
		    boolean matchedOne1=false;  // we're triangulating to
		    boolean matchedArray1=true; // the same cards over
		    int totalMatched1=0;   // several turns.
		    

		    /*//System.out.print("\nEdanState On turn "+turn+" Holmes thinks it's ");
		    for (int i=0; i<numHiddenCards; i++) {
			//System.out.print(holmesArray[i]+", ");
		    }
		 //   System.out.print("\n");*/

		    matchedArray1=compareArrays(lestradeArray, holmesArray);
		    //    System.out.print("\n");
		    if (matchedArray1) {
			numTimesMatched++;
			//System.out.println("EdanState MATCHED");
		    }
		    else {
			numTimesMatched=0;
			lestradeArray=holmesArray;
			//	System.out.println("EdanState DID NOT MATCH");
		    }
		    // System.out.println ("EdanState Elementary...");

		    int cardsknow = 0;
		    for (int i=1; i<=numCards; i++) {
			if (cards[i].solved()) {
			    cardsknow++;
			}
		    }

		    if (numCardsPerPlayer < 5) {
			
			if (numTimesMatched>8) {
			    return new Move(_CGUESS, holmesArray);
			}
			if ((numTimesMatched>6 ) && (cardsknow > (numCardsPerPlayer*(numPlayers)*55/100))) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>5) && (cardsknow > (numCardsPerPlayer*(numPlayers)*60/100))) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>4) && (cardsknow > (numCardsPerPlayer*(numPlayers)*70/100))){
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>3) && (cardsknow > (numCardsPerPlayer*(numPlayers)*70/100))) {
			    return new Move(_CGUESS, holmesArray);
			}/*
			if ((numTimesMatched>2) && (cardsknow > (numCardsPerPlayer*(numPlayers)*72/100))) {
			    return new Move(_CGUESS, holmesArray);
			    }*//*
			if (cardsknow > (numCardsPerPlayer*(numPlayers)*80/100) {
			    return new Move(_CGUESS, holmesArray);
			    }*/
		    }
				
		    else if (numCardsPerPlayer < 7) {
			
			if (numTimesMatched>12) {
			    return new Move(_CGUESS, holmesArray);
			}
			if ((numTimesMatched>6 ) && (cardsknow > (numCardsPerPlayer*(numPlayers )*54/100))) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>5) && (cardsknow > (numCardsPerPlayer*(numPlayers)*58/100))) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>4) && (cardsknow > (numCardsPerPlayer*(numPlayers )*62/100))) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>3) && (cardsknow > (numCardsPerPlayer*(numPlayers )*66/100))) {
			    return new Move(_CGUESS, holmesArray);
			}
			if ((numTimesMatched>2) && (cardsknow > (numCardsPerPlayer*(numPlayers )*70/100))) {
			    return new Move(_CGUESS, holmesArray);
			}/*
			if (cardsknow > (numCardsPerPlayer*(numPlayers - 1))*80/100) {
			    return new Move(_CGUESS, holmesArray);
			    }*/
		    }


		    else if (numCardsPerPlayer <10) {
			//System.out.println("I am playing with 8 cards");
			if (numTimesMatched>15) {
			    //System.out.println("EdanState ****BLAH*****");
			    return new Move(_CGUESS, holmesArray);
			}
			if ((numTimesMatched>12) && (cardsknow > (numCardsPerPlayer*(numPlayers))*60/100)) {
			    // System.out.println("EdanState*****70******");
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>10) && (cardsknow > (numCardsPerPlayer*(numPlayers))*65/100)) {
			    //System.out.println("EdanState******74*****");
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>8) && (cardsknow > (numCardsPerPlayer*(numPlayers))*70/100)) {
			    //System.out.println("EdanState*****79*****");
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>6) && (cardsknow > (numCardsPerPlayer*(numPlayers))*75/100)) {
			    //   System.out.println("EdanState*****82*****");
			    return new Move(_CGUESS, holmesArray);
			}
					if ((numTimesMatched>1) && (cardsknow > (numCardsPerPlayer*(numPlayers))*98/100)) {
					    //System.out.println("EdanState*********85******");
			    return new Move(_CGUESS, holmesArray);
			    
			    }
			
			if ((numTimesMatched>5) && (cardsknow > (numCardsPerPlayer*(numPlayers))*60/100)) {
			    //System.out.println("EdanState*********86******");
			    return new Move(_CGUESS, holmesArray);
			    
			}
			
		    } else {
			
			if (numTimesMatched>15) {
			    return new Move(_CGUESS, holmesArray);
			}
			if ((numTimesMatched>5 ) && (turn > (numCardsPerPlayer*(numPlayers - 1))*70/100)) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>4) && (turn > (numCardsPerPlayer*(numPlayers - 1))*73/100)) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>3) && (turn > (numCardsPerPlayer*(numPlayers - 1))*76/100)) {
			    return new Move(_CGUESS, holmesArray);
			}
			
			if ((numTimesMatched>2) && (turn > (numCardsPerPlayer*(numPlayers - 1))*79/100)) {
			    return new Move(_CGUESS, holmesArray);
			}
			if ((numTimesMatched>1) && (turn > (numCardsPerPlayer*(numPlayers - 1))*82/100)) {
			    return new Move(_CGUESS, holmesArray);
			}
		    }

	
		}
		else {
		    numTimesMatched=0;
		}
	    }
	    
	    if (false && (turn>(((numCardsPerPlayer*(numPlayers - 1))/2) + numPlayers))) {
		double limitNum;
		double currentLargestNum = 0;
		int currentplacement=0;
		int[] currentList = new int[numHiddenCards];
		//System.out.println("Going to try to guess");
		for (int i = 0; i<=numCards; i++) {
		    //  System.out.println(i);
		    cardsMultiplied[i]=1; 
		}
		
		for (int i=1; i <= numCards; i++) {
		    //System.out.println("i is "+i);
		    for (int j = 1; j<numPlayers; j++) {
			//	System.out.println("j is "+j);
			cardsMultiplied[i] = cardsMultiplied[i]*cardsAsked[i][j];
			cardsMultiplied2[i] = cardsMultiplied2[i]*cardsQuest[i][j];
			
		    }
		    cardsSummed[i]=cardsMultiplied[i]*cardsMultiplied2[i];
		}

		/*

		for (int i=1; i<=numCards; i++) {
		    //System.out.println("EH> Card "+i+" cardsummed "+cardsSummed[i]+" times");
		}
		*/

		for (int i=1; i <= numCards; i++) {
		    if (cards[i].hasPlayer(numPlayers)){
			currentList[currentplacement] = i;
			currentplacement++;
			cardsSummed[i] = -1;
		    }  // Put in Cards you know are hidden.
		    else if (cards[i].doesNotHavePlayer(numPlayers)) {
			cardsSummed[i] = -1;
		    }
		    else {
			if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum=cardsSummed[i];
			    
			}
		    }  // make a note of the most likeliest number;
		}
		limitNum=currentLargestNum;
		currentLargestNum=0;
		
		while (currentplacement < numHiddenCards) {
		    // System.out.println("limitNum is "+limitNum);
		    //System.out.println ("Guessing: got "+currentplacement+" cards so far");
		    for (int i=1; i <= numCards; i++) {
			if (cardsSummed[i]==(limitNum)) {
			    if (currentplacement < (numHiddenCards)) {
				currentList[currentplacement] = i;
				currentplacement++;
				cardsSummed[i]=-1;
				//System.out.println("Here");
			    }
			}
			else if (cardsSummed[i] > currentLargestNum) {
			    currentLargestNum = cardsSummed[i];
			    
			}
		    }
		    limitNum=currentLargestNum;
		    currentLargestNum=0;
		}
		
		return new Move(_CGUESS, currentList);
	    }

		
	    /*Edan Stuff
	    if (turn > ((numPlayer-2)*(numCardsPerPlayer))) {
		// start questioning intelligently:

		*/	    
	    
	    //round robin interrogations
	    //do not include players out of the game or players already solved
	    while(nextInterrogatee == myIndex || players[nextInterrogatee].solved())
		{
		    nextInterrogatee++;
		    
		    if(nextInterrogatee >= numPlayers)
			nextInterrogatee = 0;
		}
	    //nextInterrogatee = playerToAsk;
	    Move RET = new Move(_CINTERROGATION, askQuestion(nextInterrogatee), nextInterrogatee);
	    nextInterrogatee++;
	    if(nextInterrogatee >= numPlayers)  //reached the last player
		nextInterrogatee = 0;
	    //System.err.println("Done making a move");
	    return RET;
        
	}
      catch(Exception e)
      {
	  //System.err.println("error making move");
      	handleException(e);
      	return null;
      }
    }

    //New AskQuestion

   public int[] askQuestion(int interrogatee)
    {
	try
	    {

		int []knownArray = new int[numCards + 1];
		int []unknownArray = new int[numCards + 1];
		
		int knownCurrent = 0;
		int unknownCurrent = 0;
		
		for (int i = 1; i <= numCards; i++) {
		    if (cards[i].solved()) {
			if(!(cards[i].hasPlayer(interrogatee))) {
			    knownArray[knownCurrent] = i;        
			    knownCurrent++;
			} // This gives us an array of all cards we know who holds,
			// except for the player.
		    }
		    else {
			unknownArray[unknownCurrent] = i;
			unknownCurrent++;
		    }        // all cards we don't know who holds.
		}
		
		for(int i = 0; i < unknownCurrent; i++)
		    {
			//System.err.print("i" + i + " " + unknownArray[i] + " ");
		    }
		int numLeftToLearn = numCardsPerPlayer - players[interrogatee].cardsIKnowAbout().length;
		if(numLeftToLearn == 0)
		    {
			//	System.err.println("Error! Why are we trying to guess when we know all the cards?");			
		    }
		// How many cards that this player holds that we don't know what they
		// are

		int padding = knownCurrent - 1;
		int unknownNeeded = unknownCurrent - numLeftToLearn + 1;
		
		int questionSize = unknownNeeded + padding;
		
		int []askList = new int[questionSize];
		//System.err.println("unknownNeeded " + unknownNeeded + " padding " + padding);
		//System.err.println("unknown cards:");
		//get random cards from unknown array
		int last = unknownCurrent - 1;
		for(int i = 0; i < unknownNeeded; i++)
		    {
			//get a random index from unknown array
			int randomIndex = new Random().nextInt(last + 1);	       			
			askList[i] = unknownArray[randomIndex];
			//System.err.println(askList[i]);
			//remove this card
			unknownArray[randomIndex] = unknownArray[last];
			last--;			
		
		    }
		//System.err.println("Known cards");
		//the card not included
		int exclude = new Random().nextInt(knownCurrent);
		int next = unknownNeeded;
		for(int i = 0; i < knownCurrent; i++)
		    {
			if(i != exclude)
			    {
				askList[next] = knownArray[i];
				//System.err.println(askList[next]);
				next++;
			    }
		    }
		return askList;
	    }
	catch(Exception e)
	    {
		//	System.err.println("Error in askQuestion");
		handleException(e);
		return null;
	    }
	
    }





    /*
    public int[] askQuestion(int interrogatee)
    {
	try
	    {
		int numLeftToLearn = players[interrogatee].numCardsLeftToFind();
		if(numLeftToLearn == 0)
		    {
			//	System.err.println("Error! Why are we trying to guess when we know all the cards?");			
		    }
		// How many cards that this player holds that we don't know what they
		// are
		int []knownArray = new int[numCards + 1];
		int []unknownArray = new int[numCards + 1];
		
		int knownCurrent = 0;
		int unknownCurrent = 0;
		
		for (int i = 1; i <= numCards; i++) {
		    if (cards[i].solved()) {
			if(!(cards[i].hasPlayer(interrogatee))) {
			    knownArray[knownCurrent] = i;        
			    knownCurrent++;
			} // This gives us an array of all cards we know who holds,
			// except for the player.
		    }
		    else {
			unknownArray[unknownCurrent] = i;
			unknownCurrent++;
		    }        // all cards we don't know who holds.
		}
		int questionSize = numLeftToLearn;

		//array to keep track of which cards have been chosen
		boolean []chosen = new boolean[unknownArray.length];
		for(int i = 0; i < chosen.length; i++)
		    {
			chosen[i] = false;
		    }
		int []askList = new int[questionSize];
		//System.err.println("Making ask list");
		for(int i = 0; i < questionSize - 1; i++)
		    {
			//get a random index from unknown array
			int randomIndex = new Random().nextInt(unknownCurrent);
			while(chosen[randomIndex])
			    randomIndex = new Random().nextInt(unknownCurrent);
			askList[i] = unknownArray[randomIndex];
			//mark this card as chosen
			chosen[randomIndex] = true;
			
		    }
		int paddedCardIndex = new Random().nextInt(knownCurrent);
		askList[questionSize - 1] = knownArray[paddedCardIndex];
		return askList;
	    }
	catch(Exception e)
	    {
		//	System.err.println("Error in askQuestion");
		handleException(e);
		return null;
	    }
	
	    }*/
    
    public void inferencesAndDeductions()
    {
    	try
    	{
    		boolean changed = true;
    		while(changed)
    		{
		    //System.out.println("Thinking...");
    			changed = false;
    			for(int i = 0; i < players.length; i++)
    			{ 
			    if(players[i].makeInferences(cards, players)) {
				//System.out.print ("i");
    					changed = true;
			    }
			    //System.out.print(i+" ");
    			}    			

    			if (deductions())
			    changed = true;
    		}
    	}
    	catch(Exception e)
	    {
		//		System.err.println("Error in Inferences and Deductions");
    		handleException(e);
	    }
    }
	
	private boolean isMyCard(int toCheck)
	{
		if(cards[toCheck].playerHolding == myIndex)
			return true;
		else
			return false;
	}
	


//New Simplify


    //CHANGED 10/31
    IntegerList simplifyDisjunction(IntegerList disj, int player)
    {
	try
	    {
		//remove cards we know this player does not have
		//System.out.println("Simplifying disj for player " + player);
		//System.out.println("What the fuck is going on?");
		boolean[] toRemove = new boolean[disj.size()];
		for(int i = 0; i < toRemove.length; i++)
		    toRemove[i] = false;

		/*
		for(int i = 0; i < disj.size(); i++)
		    {
			//System.out.println(disj.getInteger(i));
		    }
		*/
		for(int i = 0; i < disj.size(); i++)
		    {
			int cardNum = disj.getInteger(i);
			//if the card is held by another player
			//if(cards[cardNum].playerHolding != Constants.UN_PLAYER && cards[cardNum].playerHolding != player)
			//System.out.println("i" + i + " card " + cardNum + " held by " + cards[cardNum].playerHolding);
			//System.out.println("Do I not have card? " + cardNum + " " + players[player].doesNotHaveCard(cardNum)); 
			if(players[player].doesNotHaveCard(cardNum))
			    {
				//System.out.println("removing card " + cardNum + " from disjunction");
				//disj.remove(i);
				toRemove[i] = true;
			    }
		    }
		//copy over to new IntegerList
		IntegerList newDisj = new IntegerList(1);
		for(int i = 0; i < toRemove.length; i++)
		    {
			if( !toRemove[i] )
			    {
				newDisj.addInteger(disj.getInteger(i));
				//System.out.println("Not removing " + disj.getInteger(i));
			    }
		    }
		//System.out.println("new disjunnction");
		for(int i = 0; i < newDisj.size(); i++)
		    {
			//System.out.println(newDisj.getInteger(i));
		    }
		
		disj = newDisj;
		
		//System.out.println("Copied over");
		for(int i = 0; i < disj.size(); i++)
		    {
			//System.out.println(disj.getInteger(i));
		    }
		
		//remove supersets
		Vector disjunctions = players[player].disjunctions;
		CardGroup toAdd = new CardGroup(disj);
		boolean []toRemoveDisj = new boolean[disjunctions.size()];
		for(int i = 0; i < toRemoveDisj.length; i++)
		    {
			toRemoveDisj[i] = false;
		    }
		for(int i = 0; i < disjunctions.size(); i++)
		    {
			CardGroup currentDisj = (CardGroup)disjunctions.get(i);
			if(toAdd.isSuperSet(currentDisj))
			    {
				//don't add
				disj.clear();
			    }
			else if(currentDisj.isSuperSet(toAdd))
			    {
				//remove currentDisj & add disj
				//disjunctions.remove(i);
				toRemoveDisj[i] = true;
			    }
		    }
		//copy over to new Disjunctions
		Vector newDisjList = new Vector(1);
		for(int i = 0; i < toRemoveDisj.length; i++)
		    {
			if(!toRemoveDisj[i])
			    newDisjList.add(disjunctions.get(i));
		    }

		players[player].disjunctions = newDisjList;
		return disj;
	    }
	
	catch(Exception e)
	    {
		//	System.err.println("Error simplifying disjunction");
		handleException(e);
		return disj;
	    }
    }



/*
    void simplifyDisjunction(IntegerList disj, int player)
    {
	try
	    {
		//remove cards we know this player does not have
		for(int i = 0; i < disj.size(); i++)
		    {
			//if the card is held by another player
			//if(cards[disj.getInteger(i)].playerHolding != Constants.UN_PLAYER && cards[disj.getInteger(i)].playerHolding != player)
			int cardNum = disj.getInteger(i);
			if(players[player].doesNotHaveCard(cardNum))
			    {
				disj.remove(i);
			    }
		    }
		
		//remove supersets
		Vector disjunctions = players[player].disjunctions;
		CardGroup toAdd = new CardGroup(disj);
		for(int i = 0; i < disjunctions.size(); i++)
		    {
			CardGroup currentDisj = (CardGroup)disjunctions.get(i);
			if(toAdd.isSuperSet(currentDisj))
			    {
				//don't add
				disj.clear();
			    }
			else if(currentDisj.isSuperSet(toAdd))
			    {
				//remove currentDisj & add disj
				disjunctions.remove(i);
			    }
		    }
	    }
	
	catch(Exception e)
	    {
		//	System.err.println("Error simplifying disjunction");
		handleException(e);
	    }
    }

*/


	/*
	void simplifyDisjunction(IntegerList disj, int player)
	{
	try
	{
		for(int i = 0; i < disj.size(); i++)
		{
			//if the card is held by another player
			if(cards[disj.getInteger(i)].playerHolding != Constants.UN_PLAYER && cards[disj.getInteger(i)].playerHolding != player)
			{
				disj.remove(i);
			}
		}
	}
	catch(Exception e)
	{
	    //	System.err.println("Error simplifying disjunction");
		handleException(e);
	}
	}*/
	
	public void playerHasCard(int cardNum, int playerNum)
	{
	try
	{
		cards[cardNum].playerHolding = playerNum;
		cards[cardNum].isHiddenCard = false;
		players[playerNum].addHasCard(cardNum, cards, players);
		for(int i = 0; i < players.length; i++)
		{
			if(i != playerNum)
				players[i].addDoesNotHave(cardNum, cards, players);
		}
		
		//check if all cards have been found for this player
		//change probabilities
	}
	catch(Exception e)
	{
	    //		System.err.println("Error in playerHasCard");
		handleException(e);		
	}
	}
	
	public void playerDoesNotHaveCard(int cardNum, int playerNum)
	{
	try
	{
		players[playerNum].addDoesNotHave(cardNum, cards, players);		
		//change probabilities for other players
	}
	catch(Exception e)
	{
	    //	System.err.println("Error in playerDoesNotCard");
		handleException(e);		
	}
	}
	
    public String name() throws Exception {
        return NAME;
    }

    public Color color() throws Exception {
        return COLOR;
    }

    public boolean interactive() throws Exception {
        return false;
    }        

    public int question(int interrogator, int[] cardlist) throws Exception
    {
    	try
    	{
			for(int i = 0; i < cardlist.length; i++)
			{
				for(int j = 0; j < myCards.length; j++)
				{		
					if(cardlist[i] == myCards[j])
					{
						return myCards[j];
					}
				}
			} 
		}
		catch(Exception e)
		{
		    //System.err.println("Error answering question.");
			handleException(e);
		}
	    return 0;
    }
    
    public void answer(int interrogatee, int[] mycardlist, int response) throws Exception
    {
    	try
    	{
	    //	System.err.println("Answer received.");
    		if(response == 0)
    		{
    			for(int i = 0; i < mycardlist.length; i++)
    			{
    				playerDoesNotHaveCard(mycardlist[i], interrogatee);
    			}
    		}
    		else
    		{
    			playerHasCard(response, interrogatee);
    		}
		//		//System.out.println("about to deduce");
		//inferencesAndDeductions();
		//System.out.println("deduced");
		//players[numPlayers].showCards();
		
		//System.out.println("EH> CARDS");

		/*
		for (int i = 1; i < cards.length; i++) {
		    cards[i].showAllPlayers();
		}

		//System.out.println("EH> PLAYERS");
		for (int i = 0; i < players.length; i++)
		{
		    // System.out.println ("Hello");
		    players[i].showAllCards();
		}
		*/
		//System.out.println("EH> CARDS ASKED");
		/*
		for (int i = 1; i <= numCards; i++) {
		    for (int j=0; j< numPlayers; j++) {
			//System.out.println("EH>  Card "+i+" asked by "+j+" "+cardsAsked[i][j]+" times");
			//System.out.println("EH> Card "+i+" asked to "+j+" "+cardsQuest[i][j]+" times");
		    }
		    }
		*/
		for (int i = 0; i<=numCards; i++) {
		    cardsMultiplied[i]=1; 
		}

		for (int i=1; i <= numCards; i++) {
		    for (int j = 1; j<numPlayers; j++) {
			cardsMultiplied[i] = cardsMultiplied[i]*cardsAsked[i][j];
		    }
		}
		/*
		for (int i=1; i<=numCards; i++) {
		    //System.out.println("Card "+i+" asked "+cardsMultiplied[i]+" times");
		    }*/
		
    	}
    	catch(Exception e)
    	{
	    //System.err.println("Error handling answer.");
    		handleException(e);
    	}
    }
    
    public void notifyPlayerExit(int playerexited) throws Exception
    {
    	try
    	{
	    //System.err.println("Player " + playerexited + " out of game.");
    		//add all of this player's cards
			int[] newCards = engine.getPlayerList(playerexited, this);
			for(int k = 0; k < newCards.length; k++)
			{
				playerHasCard(newCards[k], playerexited);
				//System.err.println("Adding p " + playerexited + " c " + newCards[k]);
			}
			//inferencesAndDeductions();
		}
		catch(Exception e)
		{
		    //System.err.println("Error in notifyPlayerExit");
			handleException(e);
		}    
    }

    public int[] forcedGuess() throws Exception
    {
    	try
    	{
	    //System.err.println("Forced Guess");
			int[] asklist = new int[numHiddenCards];
			int next = 0;
			for(int i = 1; i < (numCards + 1); i++)
			{
				//System.err.println(i + " " + players[numPlayers].hasCard(i));
				if(players[numPlayers].hasCard(i))
				{
				    //System.err.println("FGuessing " + i);
					asklist[next] = i;
					next++;
				}
			}
			//System.err.println("Done with hidden cards");
			//System.err.println("The rest of them");
			for(int i = 1; (i < cards.length) && (next < numHiddenCards); i++)
			{
			    //System.err.println(i + " " + cards[i].playerHolding);
				if(cards[i].playerHolding == Constants.UN_PLAYER && !players[numPlayers].hasCard(i))
				{
				    //System.err.println(next + " " + i + " " + numHiddenCards);
					asklist[next] = i;
					//System.err.println("FG" + i);
					next++;
				}
			}		
			//System.err.println("end of forced guess");			
			return asklist;
		}
		catch(Exception e)
		{
			handleException(e);
			return null;
		}
    }
    
     public void handleException(Exception e)
    {
	//	System.err.println("CLUELTY Error: " + e.getMessage());
		e.printStackTrace();
    }
    

    public boolean compareArrays(int[] array1, int[] array2) {
	if(array1.length != array2.length)
	    return false;

	//System.out.print("EdanState comparing arrays ");
	for (int i = 0; i < array1.length; i++)
	    {
		//System.out.print(array1[i]+" Two "+array2[i]+" ");
		int elem=array1[i];
		boolean found = false;
		for(int j = 0; j < array2.length; j++)
		    {
			if (elem==array2[j])
			    found = true;
		    }
		if(!found)
		    return false;
	    }
	return true;
	
    }
	

    public boolean deductions() {
    try
    {
		int changes = 1;
		int changed = 0;
		while (changes > 0) {
		    changes = 0;
		    for (int i = 1; i < cards.length; i++) {
			changes = changes + cards[i].deduce(cards, players);
		    }
		    for (int i = 0; i < players.length; i++) {
			changes = changes + players[i].deduce(cards, players);
		    }
		    changed = changed + changed;
		}
		if (changed>0) return true;
		else return false;
    }
    catch(Exception e)
	{
	    //	System.err.println("Error in deductions");
	    handleException(e);
	}
    return false;
    }
}
