class Rosebud extends Strategy
{
    public int count, othercount, thirdcount, thisTake, bestTake, bestBid, bestLow;
    public int nudge, leader, leadScore, leadBid, numBidding;
    public int bestCarry, thisCarry, maxPot, pot;
    public byte history[][][];

    void priv_init()
    {
	maxPot = (opponents*maxPlayableNumber)/4;
        history = new byte[opponents][maxPot][2]; 
	pot = 0;
	numBidding = 0;

	for (count = 0; count < opponents; count++)
	{
            for (othercount = 0; othercount < maxPot; othercount++)
	    {
		history[count][othercount][0] = history[count][othercount][1] = -1;
	    }
	}
    }

    // 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];
    }

    public int turn(int last_turns[], int scores[], int carryOver, int turn_no)
    {
	// Rosebud determines what the best bid in the previous turn was, given the
	// carryover and total pot available.  If it has a guess, it bids; otherwise
	// it uses the Storm strategy.

	// Store the result of last turn away for future reference
	// and set the expected next bids
	bestTake = -1;
	bestBid = 0;
	for (count = 1; count < maxPlayableNumber; count++)
	{
            last_turns[0] = count;
            thisTake = eval(last_turns, carryOver, scores);
            if (thisTake > bestTake)
            {
                bestBid = count;
		bestTake = thisTake;
            }
        }
	if (history[numBidding][pot][1] == (byte) bestBid)
	{
	    history[numBidding][pot][0] = (byte) bestBid;
	}
	else if (history[numBidding][pot][0] == (byte) bestBid)
	{
	    history[numBidding][pot][0] = history[numBidding][pot][1];   
	    history[numBidding][pot][1] = (byte) bestBid;
	}
	else
	{
	    history[numBidding][pot][1] = -1;
	    history[numBidding][pot][0] = (byte) bestBid;
	}

	// Update state need for next turn
	pot = carryOver+1;
	numBidding = 0;
	for (count = 1; count < opponents; count++)
	{
	    if (last_turns[count] > 0)
	    {
		pot = pot + last_turns[count];
		numBidding++;
		last_turns[count]++;
	    }
	}
	if (pot > maxPot) pot = maxPot;

	// OK, it's time to bid...
	nudge = (int) ((Math.random() * 5.0) / 3);	
	if (history[numBidding][pot][1] > -1) return (history[numBidding][pot][1] + nudge);
	else if (history[numBidding][pot][0] > -1) return (history[numBidding][pot][0] + nudge);

	// Hmmm... no luck that way.  Fall back to storm...
	bestTake = -1;
	bestBid = 0;
	for (count = 1; count < maxPlayableNumber; count++)
	{
            last_turns[0] = count;
            thisTake = eval(last_turns, carryOver, scores);
            if (thisTake > bestTake)
            {
                bestBid = count;
		bestTake = thisTake;
            }
        }
	return (bestBid + nudge);
    }
}
