package Cluedo.g1;

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

public class Group1Player3 extends PlayerBase {
    ClueProblem prob;

    public String name() {
        return "Psychotic Broomhead";
    }

    /** initialize a game
     */
    public void register( Cluedo game ) {
        super.register( game );
        int[] cards = decrement( (int[]) getMyCards().clone() );
        Arrays.sort( cards );

        prob = init( getNumCards(), getNumPlayers(), getNumCardsPerPlayer(),
                     cards );
        prob.owns( 0, cards, prob.c(), prob.c() );
    }

    /**
     */
    static ClueProblem init( int n, int p, int c, int[] cards ) {
        return new ProbabilisticApproach( n, p, c, cards );
    }

    /** swap the index of own player with 0
     */
    int reindex( int idx ) {
        int mine = getMyIndex();
        if ( idx == mine )
            return 0;
        if ( 0 == idx )
            return mine;
        return idx;
    }

    /** increment all card numbers by one
     */
    int[] increment( int[] cards ) {
        int[] ret = new int[cards.length];
        for ( int i=0; i<cards.length; i++ )
            ret[i] = cards[i] + 1;
        return ret;
    }

    /** decrement all card numbers by one
     */
    int[] decrement( int[] cards ) {
        int[] ret = new int[cards.length];
        for ( int i=0; i<cards.length; i++ )
            ret[i] = cards[i] - 1;
        return ret;
    }

    void updateHistory() {
        try {
            int r = mClue.currRound();
            for ( int i=Math.max(0,r-prob.p()+1); i<r; i++ )
            {
                MoveResult res = mClue.history( i );
				
				if( res != null ) {
					if ( res.type == _CINTERROGATION ) 
					{
						prob.observe( reindex( res.player ), 
							reindex( res.interrogatee ), decrement( res.cardlist ), 
							res.response 
						);
					}
				}
            }
        }
        catch (Exception e ) 
        {    
            e.printStackTrace();
        }
    }

    /** Make a move
     */
    public Move move() throws Exception {
        Move ret;

        updateHistory();

        try 
        {
            double rate = prob.rate();
            //System.out.println( "[Group1Player3] Successful rate: " + rate );

            if ( rate >= .95 ) 
            {
                int[] g = prob.guess();

                //System.out.print( "Making a guess:" );
                //prob.printcards( g );

                ret = new Move( _CGUESS, increment( g ) );
            }
            else
            {
                int who = prob.who();

                if ( who > 0 )
                {
                    int[] q =  prob.quest( who );

					if( q == null || q.length == 0 ) {
						int[] g = prob.guess();
						ret = new Move( _CGUESS, increment( g ) );
					}
					else {
						//System.out.print( "? [" + reindex( who ) + "] : " );
						//prob.printcards( q );

						ret = new Move( _CINTERROGATION, increment(q), 
										reindex( who ) );
					}
                }
                else
                {
                    int[] g = prob.guess();

                    //System.out.print( "Making a guess!:" );
                    //prob.printcards( g );

                    ret = new Move( _CGUESS, increment( g ) );
                }
            }
        } 
        catch ( Exception e ) 
        {
            e.printStackTrace();
            ret = null;
        }
        return ret;
    }

    /** reply to another player's interrogation.
     */
    public int question( int interrogator, int[] cards ) throws Exception {
        cards = decrement( cards );

        //System.out.print( "Questioned by player " + interrogator + ": " );
        //prob.printcards( cards );

        int ret = 0;
        // sort the input cards in order to eliminate the possibility
        // that other players use the order of cards to do something.
        try 
        {
            Arrays.sort( cards );
            ret = prob.reply( reindex(interrogator), cards ) + 1;
        }
        catch( Exception e ) 
        {
            e.printStackTrace();
            ret = 0;
        }

        //System.out.println( "Replied " + ret );

        return ret;
    }

    /* incorporate an answer to an interrogation into our knowledge.
     */
    public void answer( int interrogatee, int[] mycardlist, int response )
        throws Exception {

        try {
			//System.out.println( "[" + interrogatee + "] has " + response );
            if ( response > 0 )
                prob.owns( reindex( interrogatee ), new int[]{ response-1 }, 1, 1 );
            else
                prob.owns( reindex( interrogatee ), decrement( mycardlist ),
                           0, 0 );
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
    }

    /** another player has left the game.
     */
    public void notifyPlayerExit( int playerexited ) throws Exception {
        int[] cards = mClue.getPlayerList( playerexited, null );

		//System.out.print( "player " + playerexited + " exited " );

		for( int i = 0; i < cards.length; i++ ) {
			//System.out.print( cards[i] + " " );
		}

		//System.out.println();
        prob.owns( reindex( playerexited ), decrement( cards ), 
                   cards.length, cards.length );
    }

    /** time's up
     */
    public int[] forcedGuess() throws Exception {
        int[] g = prob.guess();

        //System.out.print( "Force to make a guess: " );
        //prob.printcards( g );

        return increment( g );
    }
}
