/**
 * A strategy that favors going for Yahtzees all the time.
 *
 * @author Jim Glenn
 * @version 0.1 10/20/2004
 */

public class YahtzeeBonusStrategy implements YahtzeeStrategy
{
    /**
     * Determines which dice to keep in a given situation.
     * This strategy chooses to keep the dice it has the most
     * of, breaking ties in favor of the highest number.
     *
     * @param st the current state of the game
     * @param r the current roll
     * @param rerolls the number of rerolls remaining
     * @return the dice to keep
     */

    public DiceRoll keepDice(YahtzeeState st, YahtzeeRoll r, int rerolls)
    {
	// figure out which number we have the most of
	// maxCount is the frequency; maxPips is the number so if the roll
	// is 3 4 4 6 6, maxCount = 2 and maxPips = 6 (6 wins the tie with 4
	// if the sixes category is open)

	int maxCount = r.countDice(1);
	int maxPips = 1;

	for (int pips = 2; pips <= r.countSides(); pips++)
	    if (r.countDice(pips) > maxCount
		|| (r.countDice(pips) == maxCount
		    && !st.isUsed(pips + YahtzeeState.NAUGHTS)))
		{
		    maxCount = r.countDice(pips);
		    maxPips = pips;
		}

	// construct a string containing maxCount maxPips characters
	// (so for the example above the string would be "66")

	String roll = new String();
	for (int i = 0; i < maxCount; i++)
	    roll = roll + maxPips;

	// make a DiceRoll object out of the String

	return new DiceRoll(r.countSides(), roll);
    }

    /**
     * Determines which category to play the given roll in.  This
     * strategy scores rolls in the unused category that will score
     * the most points.
     *
     * @param st the current state of the game
     * @param r the current roll
     * @return the category to play that roll in
     */

    public int pickCategory(YahtzeeState st, YahtzeeRoll r)
    {
	int maxScore = -1;
	int maxCategory = 0;
	
	for (int cat = 0; cat < nonZeroRanks.length; cat++)
	    if (!st.isUsed(nonZeroRanks[cat])
		&& st.getScore(r, nonZeroRanks[cat]) > maxScore)
		{
		    maxScore = st.getScore(r, nonZeroRanks[cat]);
		    maxCategory = nonZeroRanks[cat];
		}

	// if we can't score any points for the given roll, choose
	// which category to zero

	if (maxScore == 0)
	    {
		int cat = 0;
		while (st.isUsed(zeroRanks[cat]))
		    cat++;

		maxCategory = zeroRanks[cat];
	    }

	return maxCategory;
    }

    /**
     * The ranks for breaking ties between categories when the score will
     * be zero.  Categories at the beginning of the list will be zeroed before
     * those at the end.
     */

    protected static final int[] zeroRanks = {
	YahtzeeState.FOUR_OF_A_KIND,
	YahtzeeState.LARGE_STRAIGHT,
	YahtzeeState.FULL_HOUSE,
	YahtzeeState.THREE_OF_A_KIND,
	YahtzeeState.SMALL_STRAIGHT,
	YahtzeeState.ACES,
	YahtzeeState.DEUCES,
	YahtzeeState.TREYS,
	YahtzeeState.FOURS,
	YahtzeeState.FIVES,
	YahtzeeState.SIXES,
	YahtzeeState.YAHTZEE,
	YahtzeeState.CHANCE
    };

    /**
     * The ranks for breaking ties between categories with the score will
     * be non-zero.  Categories at the top of the list will be
     * used before those at the bottom.
     */

    protected static final int[] nonZeroRanks = {
	YahtzeeState.FOUR_OF_A_KIND,
	YahtzeeState.SMALL_STRAIGHT,
	YahtzeeState.FULL_HOUSE,
	YahtzeeState.THREE_OF_A_KIND,
	YahtzeeState.ACES,
	YahtzeeState.DEUCES,
	YahtzeeState.TREYS,
	YahtzeeState.FOURS,
	YahtzeeState.FIVES,
	YahtzeeState.SIXES,
	YahtzeeState.YAHTZEE,
	YahtzeeState.LARGE_STRAIGHT,
	YahtzeeState.CHANCE
    };

    public static void main(String[] args)
    {
	String simulatorArgs[] = {
	    "BonusYahtzeeState",        // don't change
	    "YahtzeeBonusStrategy",     // change to name of strategy class
	    "10"                          // change to # of times to run
	};

	YahtzeeSimulator.main(simulatorArgs);
    }
}
