class Opus extends Strategy
{
    public int count, othercount, thirdcount, thisTake, bestTake, bestBid, bestLow;
    public int nudge, leader, leadScore, leadBid, lastCarry, fourcount, valids, sum;
    public int bestCarry, thisCarry;
    public byte history[][][][], prevBids[], twoTurnsBack[];

    void priv_init()
    {
        history = new byte[opponents][26][26][(opponents/2)+1];
	prevBids = new byte[opponents];
	twoTurnsBack = new byte[opponents];
	lastCarry = 0;
	
	for (count = 0; count < opponents; count++)
	{
	    prevBids[count] = 0;
	    twoTurnsBack[count] = 0;
	}   

        for (count = 0; count < opponents; count++)
	{
	    for (othercount = 0; othercount < 25; othercount++)
	    {
	        for (thirdcount = 0; thirdcount < 25; thirdcount++)
		{
		    for (fourcount = 0; fourcount < (opponents/2); fourcount++)
		    {
		    	history[count][othercount][thirdcount][fourcount] = -1;
		    }
		}
	    }
	}
    }

    // Bid 4 to start.
    public int initial_turn()
    {
        return 4;
    }


    // 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)
    {
	// Elephant determines the expected bids for everyone given their
	// two most recent bids, bid of the leader, and the carryOver, and bids it.

	// Find the leader, plus some additional information with which to
	// choose a bid should there be no previous bid stored for this case.
	leadScore = 0;
	leader = 0;
	for (count = 1; count < opponents; count++)
	{
	    // Find the leader, and their score
	    if (scores[count] > leadScore)
	    {
		leadScore = scores[count];
		leader = count;
	    }
	}

	// What did the leader bid last turn?
	leadBid = last_turns[leader];

	// What was the carry?  (Count all carrys > half the number of opps the same)
	thisCarry = (carryOver > (opponents/2)) ? (opponents/2) : carryOver;

	// Store the actions of every bidder away for future reference,
	// and set the expected next bids
	for (count = 1; count < opponents; count++)
	{
	    byte lt = (byte) last_turns[count];
	    history[count][prevBids[count]][twoTurnsBack[count]][lastCarry] = lt;
	    if (lt > 25) lt = 25;
	    twoTurnsBack[count] = prevBids[count];
	    prevBids[count] = lt;
	    if (scores[count] < 1) last_turns[count] = 0;
	    else if (history[count][prevBids[count]][twoTurnsBack[count]][thisCarry] == -1)
	    {
		sum = 0;
		valids = 0;
		for (othercount = 0; othercount < (opponents/2); othercount++)
		{
		    if (history[count][prevBids[count]][twoTurnsBack[count]][othercount] > -1)
		    {
			sum = sum + history[count][prevBids[count]][twoTurnsBack[count]][othercount];
			valids++;
		    }
		}
		if (valids == 0)
		{
		    if (lt > 0) last_turns[count]++;
		}
		else last_turns[count] = (sum / valids);
	    }
	    else last_turns[count] = history[count][prevBids[count]][twoTurnsBack[count]][thisCarry];
	}

	lastCarry = thisCarry;
	
	// Now find the best bid given the assumed bids
	bestTake = -1;
	bestBid = 0;
	bestLow = 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);
            if ((thisTake > bestTake) || ((thisTake == bestTake) && (thisCarry > bestCarry) && ((thisCarry-bestCarry) > (thisTake-bestTake))))
            {
                bestBid = count;
		bestTake = thisTake;
		bestCarry = thisCarry;
		if (count < 12) bestLow = count;
            }
        }

	// 1/4 of the time add 1 to the bid for confusion's sake
	nudge = (int) ((Math.random() * 5.0) / 3);
//	nudge = 0;

	// Provide some time for the memory to load...
//	if (turn_no < 200) return (leadBid+1+nudge);

	// Hold on - I don't think > 10 should _ever_ be ideal
	if (bestBid > 12) bestBid = bestLow;
	
	// Make sure we return a valid bid
	if ((bestBid + nudge) > maxPlayableNumber) nudge =0;

	// Now bid...
	return (bestBid + nudge);
    }
}