// July 1999
package net.sf.nebulacards.main;
import net.sf.nebulacards.util.proc.CommonRules;
import net.sf.nebulacards.util.proc.DealProc;
import net.sf.nebulacards.util.proc.DealProcGame;
/**
* Base class for card game rules.
*
* @author James Ranson
*/
public abstract class Rules extends Game implements CardOrdering, DealProcGame {
private String name;
/**
* The trump suit. A suit constant from PlayingCard or NO_TRUMP. This MUST
* be set to a valid value if you want to use the default whoWinsTrick
* method.
*
* @see #NO_TRUMP
* @see PlayingCard
*/
private int trump;
/**
* A text name for the trump suit. This helps user interfaces to display
* something meaningful, instead of just a number.
*/
private String trumpName;
protected Rules(String name, int trump, String trumpName) {
this.name = name;
this.trump = trump;
this.trumpName = trumpName;
}
/**
* Indicates that no trump suit is set.
*/
public static final int NO_TRUMP = -1;
/**
* Get a full deck for this game. The default implementation returns
* PileOfCards.getStandardDeck().
*
* @see PileOfCards#getStandardDeck()
* @version 0.2
* @return A full deck.
*/
public PileOfCards getDeck() {
return PileOfCards.getStandardDeck();
}
/**
* Deal the cards. This is just a wrapper for CommonRules.deal().
*
* @see net.sf.nebulacards.util.proc/CommonRules(net.sf.nebulacards.main.PileOfCards,int)
* @return The cards in each player's hand.
*/
public PileOfCards[] deal() {
return CommonRules.deal(getDeck());
}
public String getName() {
return name;
}
/**
* Get the trump suit. This returns the value stored in the <i>trump</i>
* member variable.
*
* @see #trump
* @return The trump suit.
*/
public final int getTrump() {
return trump;
}
/**
* Get the trump suit name. This returns the value stored in the
* <i>trumpName</i> member variable.
*
* @see #trumpName
* @return The trump suit name.
*/
public final String getTrumpName() {
return trumpName;
}
/**
* Set the trump suit. The default behaviour is to ignore the card and set
* the value to NO_TRUMP.
*
* @see #NO_TRUMP
* @param c
* The final card dealt.
*/
public void setTrump(PlayingCard c) {
trump = NO_TRUMP;
}
/**
* Check if the given card is a legal play in this context. This is entirely
* dependent on the particular game, so no default behaviour is provided.
*
* @param beenPlayed
* All the cards that have been played during this hand.
* @param tableau
* The cards that are currently on the table.
* @param hand
* The players hand, including the card in question.
* @param c
* The card to be verified.
* @return True if card is a legal play, false otherwise.
*/
public abstract boolean validPlay(PileOfCards beenPlayed, Tableau tableau,
PileOfCards hand, PlayingCard c);
/**
* Determine who wins the trick.
*
* @see net.sf.nebulacards.util.proc.CommonRules.whoWinsTrick(net.sf.nebulacards.main.Tableau,int)
* @param tableau
* All the cards in the trick.
* @return The table position of the winning card.
*/
public int whoWinsTrick(Tableau tableau) {
return CommonRules.whoWinsTrick(tableau, trump);
}
/**
* Update the scores and bags. Calculate and set the new scores and bags. By
* default, this calls score( PileOfCards[], int[], int[], int[] ).
*
* @param hands
* The cards each player won from tricks.
* @param p
* The players.
*/
public abstract void score(PileOfCards[] hands, Player[] p);
/**
* Provide a result for this game. Called after every hand to see if the
* game is done.
*
* @param p
* The players.
* @return The result of the game.
*/
public abstract GameResult done(Player[] p);
/**
* This method is called at the end of every trick. The default
* implementation does nothing.
*
* @version 0.3
* @param tableau
* The tableau
* @param winner
* The winner of the trick
*/
public void trickDone(Tableau tableau, int winner) {
// do nothing
}
/**
* Should the hand be terminated prematurely. This is called at various
* places in the game loop. If it ever returns true, the hand is considered
* finished even if there are cards left. The default implementation always
* returns false.
*
* @version 0.2
* @return True if hand is to be ended prematurely, false otherwise.
*/
public boolean quitHand() {
return false;
}
/**
* Who should play the next card. The default implementation conducts play
* in the clockwise direction where the winner of the last trick leads.
*
* @version 0.2
* @param first
* true if the trick is currently empty (i.e. asking who leads)
* @param lastCard
* The player who just played (only defined when <i>first</i> is
* false).
* @param lastWinner
* The player who won the last trick (only defined when <i>first</i>
* is true. lastWinner == -1 on the first trick of the hand.
* @return Who should play next or -1 to let the server decide.
*/
public int whoPlaysNext(boolean first, int lastCard, int lastWinner) {
if (first)
return lastWinner;
return ((lastCard + 1) % 4);
}
/**
* Satisfy the CardOrdering interface. Default implementation: cards are
* ordered in increasing order by value within each suit.
*
* @see CardOrdering
*/
public boolean precedes(PlayingCard a, PlayingCard b) {
if (a.getSuit() == b.getSuit())
return (a.getValue() < b.getValue());
else
return (a.getSuit() < b.getSuit());
}
/**
* Get procedure ordering. This method is called at the beginning of each
* hand in order to determine the order in which to execute the built-in
* procedures, such as bidding and passing. The default implementation gives
* the following order: deal cards, bidding, passing, asking for trump,
* direct com. If the array contains a procedure that is not supported by
* the ruleset, that entry will be silently ignored.
*
* @return An array of game procedures, to be traversed from lowest index to
* highest.
* @version 0.5
*/
public GameProcedure[] getProcedureOrdering() {
GameProcedure[] defaultOrder = { new DealProc(),
new GameProcedure(GameProcedure.BIDDING),
new GameProcedure(GameProcedure.PASSING),
new GameProcedure(GameProcedure.ASKTRUMP),
new GameProcedure(GameProcedure.DIRECTCOM) };
return defaultOrder;
}
}