class Vizzini extends Strategy
{
    public int count, thisTake, bestTake, bestBid, bestValue;
    public int bestCarry, thisCarry, lastBid, max2;
    public int history[], prevBids[], twoTurnsBack[], threeTurnsBack[], bidValue[];

    void priv_init()
    {
	max2 = maxPlayableNumber + 2;
        history = new int[opponents];
	prevBids = new int[opponents];
	twoTurnsBack = new int[opponents];
	threeTurnsBack = new int[opponents];
	bidValue = new int[max2];

	for (count = 0; count < opponents; count++)
	{
	    history[count] = -1;
	    prevBids[count] = 0;
	    twoTurnsBack[count] = 0;
	    threeTurnsBack[count] = 0;
	}
    }

    // Bid 5 to start.
    public int initial_turn()
    {
        return 5;
    }


    // A tiny little turn-evaluator:
    int eval(int turns[], int carry, int scores[])
    {
        int i, j, sum, t, parts, t0;

        sum = carry;
        parts = 0;
        t0 = 0;
        for (i = 0; i < opponents; i++) if ( scores[i] > 0 )
        {
            if ( turns[i] > 0 )
            {
                sum  += turns[i];
                t = 0;
                for (j = 0; j < opponents; j++)
                {
                    if ( turns[j] > 0 && turns[i] >= turns[j] ) t++;
                }
                if (i == 0) t0 = t;
                parts   += t;
            }
        }
        sum += stepBonus;
        if ( parts == 0 ) return 0;
        return (int) ( sum * t0 ) / parts - turns[0];
    }

    // A tiny little carry-over evaluator:
    int change(int turns[], int carry, int scores[])
    {
        int i, j, sum, t, parts, t0;

        sum = carry;
        parts = 0;
        t0 = 0;
        for (i = 0; i < opponents; i++) if ( scores[i] > 0 )
        {
            if ( turns[i] > 0 )
            {
                sum  += turns[i];
                t = 0;
                for (j = 0; j < opponents; j++)
                {
                    if ( turns[j] > 0 && turns[i] >= turns[j] ) t++;
                }
                if (i == 0) t0 = t;
                parts   += t;
            }
        }
        sum += stepBonus;
        if ( parts == 0 ) return 0;
        return (sum%parts);
    }

    public int turn(int last_turns[], int scores[], int carryOver, int turn_no)
    {
	// Vizzini tries to figure out the best bid for the past four turns, giving
	// extra weight to the most recent turn.  Then it checks to see what the _real_
	// best bid was last time it _thought_ that was an ideal bid, and bids that.
	// Never go in against a Sicilian, when death is on the line!

	// All we really do is loop...
	// Clear the bid values
	for (count = 0; count < max2; count++)
	{
	    bidValue[count] = 0;
	}
	
	// Go through the most recent turn
	bestTake = -1;
	bestBid = 0;
	bestCarry = 0;
	for (count = 1; count < maxPlayableNumber; count++)
	{
            last_turns[0] = count;
            thisTake = eval(last_turns, carryOver, scores);
	    thisCarry = change(last_turns, carryOver, scores);
            bidValue[count] = bidValue[count] + (2 * thisTake);
            if ((thisTake > bestTake) || ((thisTake == bestTake) && (thisCarry > bestCarry)))
            {
                bestBid = count;
		bestTake = thisTake;
		bestCarry = thisCarry;
            }
        }

	// What should I do next time?
	history[lastBid] = bestBid;

	// OK, now check out the other three turns...
	for (count = 1; count < maxPlayableNumber; count++)
	{
            prevBids[0] = count;
	    twoTurnsBack[0] = count;
	    threeTurnsBack[0] = count;
            thisTake = eval(prevBids, carryOver, scores);
            bidValue[count] = bidValue[count] + thisTake;
	    thisTake = eval(twoTurnsBack, carryOver, scores);
	    bidValue[count] = bidValue[count] + thisTake;
	    thisTake = eval(threeTurnsBack, carryOver, scores);
	    bidValue[count] = bidValue[count] + thisTake;
	}

	// Update history...
	for (count = 1; count < opponents; count++)
	{
	    threeTurnsBack[count] = twoTurnsBack[count];
	    twoTurnsBack[count] = prevBids[count];
	    prevBids[count] = last_turns[count];
	}
	
	// Which bid scored best?
	bestBid = 0;
	bestValue = -1;
	for (count = 1; count < maxPlayableNumber; count++)
	{
            if (bidValue[count] > bestValue)
            {
                bestBid = count;
		bestValue = bidValue[count];
            }
        }	

	// OK, pick a bid.
	lastBid = bestBid;
	
	// Hmmm... was there a better choice last time I saw this?
	if (history[bestBid] > -1) return (history[bestBid]);
	
	// Nope, just try it out...
	else return(bestBid);
    }
}