summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/jrummikub/control/AbstractSettingsControl.java74
-rw-r--r--src/jrummikub/control/ApplicationControl.java18
-rw-r--r--src/jrummikub/control/GameControl.java79
-rw-r--r--src/jrummikub/control/LoginControl.java1
-rw-r--r--src/jrummikub/control/RoundControl.java166
-rw-r--r--src/jrummikub/control/SaveControl.java14
-rw-r--r--src/jrummikub/control/SettingsControl.java17
7 files changed, 321 insertions, 48 deletions
diff --git a/src/jrummikub/control/AbstractSettingsControl.java b/src/jrummikub/control/AbstractSettingsControl.java
index ee0c96c..2904df4 100644
--- a/src/jrummikub/control/AbstractSettingsControl.java
+++ b/src/jrummikub/control/AbstractSettingsControl.java
@@ -49,6 +49,9 @@ public abstract class AbstractSettingsControl {
.asList(ISettingsPanel.PLAYER_COLORS)));
}
+ /**
+ * Add event listeners to abstract settings control
+ */
protected void addListeners() {
addPlayerSettingsListeners();
@@ -57,6 +60,9 @@ public abstract class AbstractSettingsControl {
addVariantListeners();
}
+ /**
+ * Add event listeners to the player settings panel
+ */
private void addPlayerSettingsListeners() {
connections.add(view.getSettingsPanel().getAddPlayerEvent()
.add(new IListener() {
@@ -95,6 +101,9 @@ public abstract class AbstractSettingsControl {
}));
}
+ /**
+ * Add the first half of event listeners to option panel
+ */
private void addOptionListeners1() {
connections.add(view.getSettingsPanel()
.getChangeInitialMeldThresholdEvent()
@@ -134,6 +143,9 @@ public abstract class AbstractSettingsControl {
}));
}
+ /**
+ * Add the second half of event listeners to option panel
+ */
private void addOptionListeners2() {
connections.add(view.getSettingsPanel().getChangeHighestValueEvent()
.add(new IListener1<Integer>() {
@@ -168,7 +180,7 @@ public abstract class AbstractSettingsControl {
update();
}
}));
-
+
connections.add(view.getSettingsPanel().getChangeSeeHandSizeEvent()
.add(new IListener1<Boolean>() {
@Override
@@ -212,6 +224,11 @@ public abstract class AbstractSettingsControl {
view.showSettingsPanel(true);
}
+ /**
+ * Finds the next unused player color
+ *
+ * @return an unused color
+ */
protected Color findUnusedColor() {
Color color = null;
colorLoop: for (Color c : ISettingsPanel.PLAYER_COLORS) {
@@ -226,6 +243,14 @@ public abstract class AbstractSettingsControl {
return color;
}
+ /**
+ * Sets a player's color
+ *
+ * @param i
+ * index of player
+ * @param color
+ * color to be set
+ */
private void setPlayerColor(int i, Color color) {
PlayerSettings player = settings.getPlayerList().get(i);
@@ -244,16 +269,36 @@ public abstract class AbstractSettingsControl {
update();
}
+ /**
+ * Sets a player's name
+ *
+ * @param i
+ * index of player
+ * @param name
+ * name to be set
+ */
private void setPlayerName(int i, String name) {
settings.getPlayerList().get(i).setName(name);
update();
}
+ /**
+ * Removes a player from the planned game
+ *
+ * @param i
+ * index of player
+ */
private void removePlayer(int i) {
settings.getPlayerList().remove(i);
update();
}
+ /**
+ * Checks the settings for ambiguous or missing data and sets error/warning
+ * if necessary
+ *
+ * @return boolean check correct
+ */
protected boolean checkSettings() {
if (!checkName()) {
return false;
@@ -270,6 +315,11 @@ public abstract class AbstractSettingsControl {
return true;
}
+ /**
+ * Checks if unique player name is present for each player
+ *
+ * @return is player name ok
+ */
private boolean checkName() {
for (PlayerSettings player : settings.getPlayerList()) {
if (player.getName().isEmpty()) {
@@ -302,6 +352,11 @@ public abstract class AbstractSettingsControl {
return true;
}
+ /**
+ * Check options leading to errors
+ *
+ * @return options ok
+ */
private boolean checkErrors() {
int totalStonesDealt = settings.getNumberOfStonesDealt()
* settings.getPlayerList().size();
@@ -324,6 +379,9 @@ public abstract class AbstractSettingsControl {
return true;
}
+ /**
+ * Check all options and player settings for entries causing warnings
+ */
private void checkWarnings() {
if (settings.getInitialMeldThreshold() >= 100) {
view.getSettingsPanel().setError(
@@ -356,10 +414,24 @@ public abstract class AbstractSettingsControl {
}
}
+ /**
+ * Add new player to the planned game
+ */
abstract protected void addPlayer();
+ /**
+ * Set the type of a player
+ *
+ * @param i
+ * index of player
+ * @param type
+ * type to be set
+ */
abstract protected void setPlayerType(int i, Type type);
+ /**
+ * Show newly chosen options in view
+ */
abstract protected void update();
}
diff --git a/src/jrummikub/control/ApplicationControl.java b/src/jrummikub/control/ApplicationControl.java
index 752cb3c..71de63e 100644
--- a/src/jrummikub/control/ApplicationControl.java
+++ b/src/jrummikub/control/ApplicationControl.java
@@ -118,6 +118,9 @@ public class ApplicationControl {
});
}
+ /**
+ * Create a new network login control
+ */
private void createLoginControl() {
loginControl = new LoginControl(view);
loginControl.getLoginEvent().add(new IListener1<LoginData>() {
@@ -135,6 +138,9 @@ public class ApplicationControl {
loginControl.startLogin();
}
+ /**
+ * End all controls in case of e.g. quit event
+ */
private void abortControls() {
if (settingsControl != null) {
settingsControl.abort();
@@ -191,6 +197,12 @@ public class ApplicationControl {
settingsControl.startSettings();
}
+ /**
+ * Adds events listeners to game control events
+ *
+ * @param gameControl
+ * of current game
+ */
private void addGameControlListeners(GameControl gameControl) {
gameControl.getEndOfGameEvent().add(new IListener() {
@Override
@@ -200,6 +212,12 @@ public class ApplicationControl {
});
}
+ /**
+ * Create a new network game control
+ *
+ * @param loginData
+ * users login data for channel
+ */
private void createNetworkControl(LoginData loginData) {
ConnectionControl connectionControl = new ConnectionControl(loginData);
networkControl = new NetworkControl(loginData, connectionControl,
diff --git a/src/jrummikub/control/GameControl.java b/src/jrummikub/control/GameControl.java
index c038f9a..736e440 100644
--- a/src/jrummikub/control/GameControl.java
+++ b/src/jrummikub/control/GameControl.java
@@ -33,11 +33,11 @@ public class GameControl {
* Constructor
*
* @param gameSettings
- * the game settings
+ * the game settings
* @param saveControl
- * the save control
+ * the save control
* @param view
- * the view
+ * the view
*/
public GameControl(GameSettings gameSettings, SaveControl saveControl,
IView view) {
@@ -49,8 +49,9 @@ public class GameControl {
gameState = new GameState();
saveControl.setGameState(gameState);
- gameState.setFirstRoundFirstPlayer((int) (Math.random() * gameSettings
- .getPlayerList().size()));
+ gameState
+ .setFirstRoundFirstPlayer((int) (Math.random() * gameSettings
+ .getPlayerList().size()));
}
connections.add(view.getNewRoundEvent().add(new IListener() {
@@ -84,11 +85,17 @@ public class GameControl {
return endOfGameEvent;
}
+ /**
+ * Ends the running game
+ */
private void endGame() {
removeListeners();
endOfGameEvent.emit();
}
+ /**
+ * Removes all listeners from the connection
+ */
private void removeListeners() {
for (Connection c : connections) {
c.remove();
@@ -106,9 +113,9 @@ public class GameControl {
* Continues game after loading
*
* @param gameState
- * the saved GameState (Players, startplayer, points)
+ * the saved GameState (Players, startplayer, points)
* @param roundState
- * the saved RoundState (activePlayer, Table, heap etc)
+ * the saved RoundState (activePlayer, Table, heap etc)
*/
public void continueGame(GameState gameState, IRoundState roundState) {
this.gameState = gameState;
@@ -135,6 +142,9 @@ public class GameControl {
view.clearView();
}
+ /**
+ * Start a new round within the existing game
+ */
protected void startRound() {
if (roundControl != null) {
return;
@@ -147,22 +157,29 @@ public class GameControl {
roundControl.startRound();
}
+ /**
+ * Prepare a new round by setting start player, adding listeners
+ *
+ * @param roundState
+ * of current round
+ */
private void prepareRound(IRoundState roundState) {
saveControl.setRoundState(roundState);
if (roundState != null) {
- roundState.setActivePlayerNumber(gameState.getFirstRoundFirstPlayer()
- + gameState.getScores().size());
+ roundState.setActivePlayerNumber(gameState
+ .getFirstRoundFirstPlayer() + gameState.getScores().size());
}
roundControl = createRoundControl(roundState);
- roundControl.getRoundStateUpdateEvent().add(new IListener1<IRoundState>() {
- @Override
- public void handle(IRoundState newState) {
- gameState = newState.getGameState();
- gameSettings = newState.getGameSettings();
- }
- });
+ roundControl.getRoundStateUpdateEvent().add(
+ new IListener1<IRoundState>() {
+ @Override
+ public void handle(IRoundState newState) {
+ gameState = newState.getGameState();
+ gameSettings = newState.getGameSettings();
+ }
+ });
roundControl.getEndOfRoundEvent().add(new IListener1<Score>() {
@Override
public void handle(Score roundScore) {
@@ -179,19 +196,40 @@ public class GameControl {
});
}
+ /**
+ * Creates a new round State
+ *
+ * @return the round state
+ */
protected IRoundState createRoundState() {
return new RoundState(gameSettings, gameState);
}
+ /**
+ * Creates a new round control with the specified round state
+ *
+ * @param roundState
+ * for new round control
+ * @return the round control
+ */
protected RoundControl createRoundControl(IRoundState roundState) {
return new RoundControl(roundState, view);
}
+ /**
+ * Restarts round after loading
+ */
private void restartRound() {
roundControl = null;
startRound();
}
+ /**
+ * Sets the score and default values for saving when round ends
+ *
+ * @param roundScore
+ * score for ended round
+ */
private void endOfRound(Score roundScore) {
gameState.getScores().add(roundScore);
saveControl.setRoundState(null);
@@ -200,17 +238,24 @@ public class GameControl {
showScorePanel();
}
+ /**
+ * Sets score panel visible
+ */
private void showScorePanel() {
view.showSidePanel(false);
view.setBottomPanel(BottomPanelType.WIN_PANEL);
view.getScorePanel().setPlayers(gameSettings.getPlayerList());
view.getScorePanel().setScores(gameState.getScores());
- view.getScorePanel().setAccumulatedScore(gameState.getAccumulatedScore());
+ view.getScorePanel().setAccumulatedScore(
+ gameState.getAccumulatedScore());
view.getScorePanel().update();
view.showScorePanel(true);
}
+ /**
+ * Exits System without warnings if no game control is active
+ */
private void endProgram() {
System.exit(0);
}
diff --git a/src/jrummikub/control/LoginControl.java b/src/jrummikub/control/LoginControl.java
index ccf6e2e..f26b0d6 100644
--- a/src/jrummikub/control/LoginControl.java
+++ b/src/jrummikub/control/LoginControl.java
@@ -36,7 +36,6 @@ public class LoginControl {
@Override
public void handle(LoginData loginData) {
abort();
- // TODO connectPanel anzeigen
loginEvent.emit(loginData);
}
}));
diff --git a/src/jrummikub/control/RoundControl.java b/src/jrummikub/control/RoundControl.java
index c24a7f5..b378430 100644
--- a/src/jrummikub/control/RoundControl.java
+++ b/src/jrummikub/control/RoundControl.java
@@ -37,10 +37,29 @@ import jrummikub.view.IView.BottomPanelType;
* Controller that manages a single round of rummikub
*/
public class RoundControl {
+ /**
+ * Enum summarizing the different types of invalid turns to set the correct
+ * panel message
+ */
public enum InvalidTurnType {
- INVALID_SETS, INITIAL_MELD_ERROR, NOT_ENOUGH_POINTS
+ /** There are invalid set(s) on the table */
+ INVALID_SETS,
+ /**
+ * The player tried to modify the table without providing the initial
+ * meld threshold first
+ */
+ INITIAL_MELD_ERROR,
+ /**
+ * The player didn't provide enough points for the initial meld
+ * threshold
+ */
+ NOT_ENOUGH_POINTS
}
+ /**
+ * Table, stone sets and type of an invalid turn to allow a user to track
+ * his own errors
+ */
public static class InvalidTurnInfo implements Serializable {
private static final long serialVersionUID = -3591000741414366776L;
@@ -48,6 +67,16 @@ public class RoundControl {
private InvalidTurnType type;
private ArrayList<StoneSet> invalidSets;
+ /**
+ * Creates new InvalidTurnInfo
+ *
+ * @param table
+ * the table after the turn
+ * @param type
+ * the type of the invalid turn
+ * @param invalidSets
+ * the sets causing the turn to be invalid
+ */
public InvalidTurnInfo(ITable table, InvalidTurnType type,
Collection<StoneSet> invalidSets) {
this.table = (ITable) table.clone();
@@ -55,14 +84,29 @@ public class RoundControl {
this.invalidSets = new ArrayList<StoneSet>(invalidSets);
}
+ /**
+ * Getter for table
+ *
+ * @return the table
+ */
public ITable getTable() {
return table;
}
+ /**
+ * Getter for invalid turn type
+ *
+ * @return the type
+ */
public InvalidTurnType getType() {
return type;
}
+ /**
+ * Getter for the invalid sets
+ *
+ * @return invalid sets
+ */
public List<StoneSet> getInvalidSets() {
return invalidSets;
}
@@ -86,9 +130,9 @@ public class RoundControl {
* Create a new RoundControl using the given gameState and view
*
* @param roundState
- * initial round state
+ * initial round state
* @param view
- * view used for user interaction
+ * view used for user interaction
*/
protected RoundControl(IRoundState roundState, IView view, boolean mayPause) {
this.roundState = roundState;
@@ -160,11 +204,21 @@ public class RoundControl {
}
}
+ /**
+ * Sets the current round state
+ *
+ * @param state
+ * to be set
+ */
protected void setRoundState(IRoundState state) {
roundState = state;
roundStateUpdateEvent.emit(state);
}
+ /**
+ * Prepare a player's turn by checking the player types and setting the
+ * correct turn control
+ */
protected void prepareTurn() {
doPrepareTurn();
@@ -178,6 +232,9 @@ public class RoundControl {
}
}
+ /**
+ * Prepare turn by setting the view components
+ */
protected void doPrepareTurn() {
updateSidePanel();
@@ -190,16 +247,20 @@ public class RoundControl {
}
view.getTablePanel().setStoneSets(roundState.getTable().clone());
- view.setCurrentPlayerName(roundState.getActivePlayer().getPlayerSettings()
- .getName());
- view.setCurrentPlayerColor(roundState.getActivePlayer().getPlayerSettings()
- .getColor());
- view.setCurrentPlayerHasLaidOut(roundState.getActivePlayer().getLaidOut());
+ view.setCurrentPlayerName(roundState.getActivePlayer()
+ .getPlayerSettings().getName());
+ view.setCurrentPlayerColor(roundState.getActivePlayer()
+ .getPlayerSettings().getColor());
+ view.setCurrentPlayerHasLaidOut(roundState.getActivePlayer()
+ .getLaidOut());
turnControl = createTurnControl(roundState.getActivePlayer()
.getPlayerSettings().getType());
}
+ /**
+ * Start a players turn with the correct turn control
+ */
protected void startTurn() {
if (turnControl == null) {
doPrepareTurn();
@@ -250,6 +311,9 @@ public class RoundControl {
turnControl.startTurn();
}
+ /**
+ * Update the side panel to show correct player order and heap size
+ */
private void updateSidePanel() {
view.showSidePanel(true);
view.getSidePanel().setGameSettings(roundState.getGameSettings());
@@ -263,25 +327,49 @@ public class RoundControl {
view.getSidePanel().setHeapSize(roundState.getGameHeap().getSize());
}
- /** Override this */
+ /**
+ * Override this
+ *
+ * @param turnControl
+ * current turn control
+ */
protected void addTurnControlListeners(ITurnControl turnControl) {
}
+ /**
+ * Creates new turn control of the specified type
+ *
+ * @param type
+ * of the new turn control
+ * @return the new turn control
+ */
protected ITurnControl createTurnControl(Type type) {
return TurnControlFactory.getFactory(type).create();
}
+ /**
+ * Deal each player the number of stones specified in the game settings
+ * (numberOfStonesDealt)
+ */
protected void deal() {
for (int i = 0; i < roundState.getPlayerCount(); i++) {
IHand hand = roundState.getNthNextPlayer(i).getHand();
- for (int j = 0; j < roundState.getGameSettings().getNumberOfStonesDealt(); j++) {
- hand.drop(roundState.getGameHeap().drawStone(), new Position(0, 0));
+ for (int j = 0; j < roundState.getGameSettings()
+ .getNumberOfStonesDealt(); j++) {
+ hand.drop(roundState.getGameHeap().drawStone(), new Position(0,
+ 0));
}
}
view.getSidePanel().setHeapSize(roundState.getGameHeap().getSize());
}
+ /**
+ * End the players turn
+ *
+ * @param invalidTurnInfo
+ * info about the player's last turn
+ */
protected void endOfTurn(InvalidTurnInfo invalidTurnInfo) {
boolean wasAI = turnControl instanceof AIControl;
boolean wasHuman = turnControl instanceof HumanTurnControl;
@@ -298,16 +386,16 @@ public class RoundControl {
view.setInvalidStoneSets(invalidTurnInfo.getInvalidSets());
switch (invalidTurnInfo.getType()) {
- case INITIAL_MELD_ERROR:
- view.setInitialMeldFirstError();
- break;
- case INVALID_SETS:
- view.setStoneCollectionHidden(true);
- break;
- case NOT_ENOUGH_POINTS:
- view.setInitialMeldError(roundState.getGameSettings()
- .getInitialMeldThreshold());
- break;
+ case INITIAL_MELD_ERROR:
+ view.setInitialMeldFirstError();
+ break;
+ case INVALID_SETS:
+ view.setStoneCollectionHidden(true);
+ break;
+ case NOT_ENOUGH_POINTS:
+ view.setInitialMeldError(roundState.getGameSettings()
+ .getInitialMeldThreshold());
+ break;
}
if (wasAI) {
@@ -330,6 +418,9 @@ public class RoundControl {
}
}
+ /**
+ * Set the next player as active player if the round is not finished
+ */
protected void nextPlayer() {
view.setSelectedStones(Collections.<Stone> emptyList());
view.setInvalidStoneSets(Collections.<StoneSet> emptyList());
@@ -356,6 +447,9 @@ public class RoundControl {
}
}
+ /**
+ * Ends the current round and emits an event setting the score
+ */
void endOfRound() {
removeListeners();
Score roundScore = score();
@@ -363,12 +457,20 @@ public class RoundControl {
roundFinished = true;
}
+ /**
+ * Removes all listeners form the connections
+ */
private void removeListeners() {
for (Connection c : connections) {
c.remove();
}
}
+ /**
+ * Calculate the score for the current round and the total game score
+ *
+ * @return the new score
+ */
private Score score() {
List<Boolean> winners = new ArrayList<Boolean>();
List<Integer> points = new ArrayList<Integer>();
@@ -393,10 +495,12 @@ public class RoundControl {
stonePoints = playerHand.isInitialMeldPossible(roundState
.getGameSettings()) ? 200 : 100;
} else {
- stonePoints = playerHand.getStonePoints(roundState.getGameSettings());
+ stonePoints = playerHand.getStonePoints(roundState
+ .getGameSettings());
}
- bestScore = updateBestScore(bestScore, -stonePoints, playerHand.getSize());
+ bestScore = updateBestScore(bestScore, -stonePoints,
+ playerHand.getSize());
points.add(-stonePoints);
pointSum += stonePoints;
@@ -415,6 +519,18 @@ public class RoundControl {
return new Score(winners, points);
}
+ /**
+ * Update the best score to find the winner in case of special game end
+ * (everybody still has stones on hand)
+ *
+ * @param bestScore
+ * of previous rounds
+ * @param stonePoints
+ * sum of points still left on hands
+ * @param size
+ * number of players in game (= size of score list in columns)
+ * @return Pair of maximum points and hand size
+ */
private static Pair<Integer, Integer> updateBestScore(
Pair<Integer, Integer> bestScore, int stonePoints, int size) {
if (bestScore.getFirst() == stonePoints) {
@@ -435,6 +551,10 @@ public class RoundControl {
return restartRoundEvent;
}
+ /**
+ * Redeal stones and restart round if a player was allowed to redeal and
+ * chose to do so
+ */
private void redeal() {
turnControl = null;
for (Connection c : new ArrayList<Connection>(connections)) {
diff --git a/src/jrummikub/control/SaveControl.java b/src/jrummikub/control/SaveControl.java
index 4134aec..1b88d1c 100644
--- a/src/jrummikub/control/SaveControl.java
+++ b/src/jrummikub/control/SaveControl.java
@@ -107,6 +107,13 @@ public class SaveControl {
this.roundState = roundState;
}
+ /**
+ * Loads the specified file and sets game state and round state. If the file
+ * selected cannot be handled, an error will occur and show
+ *
+ * @param file
+ * to be loaded
+ */
private void load(File file) {
try {
ObjectInputStream stream = new ObjectInputStream(
@@ -140,6 +147,13 @@ public class SaveControl {
return loadErrorEvent;
}
+ /**
+ * Saves the current game state and round state to a file with the specified
+ * file name
+ *
+ * @param file
+ * file to save game in
+ */
private void save(File file) {
if (gameState == null || gameSettings == null) {
return;
diff --git a/src/jrummikub/control/SettingsControl.java b/src/jrummikub/control/SettingsControl.java
index 6576101..4675bc7 100644
--- a/src/jrummikub/control/SettingsControl.java
+++ b/src/jrummikub/control/SettingsControl.java
@@ -25,9 +25,9 @@ public class SettingsControl extends AbstractSettingsControl {
* Create a new settings control
*
* @param view
- * the view to use
+ * the view to use
* @param settings
- * initial game settings
+ * initial game settings
*/
public SettingsControl(IView view, GameSettings settings) {
super(view, settings);
@@ -48,8 +48,8 @@ public class SettingsControl extends AbstractSettingsControl {
}
/**
- * the start game event is emitted when the user wants to start a game and the
- * settings made are valid
+ * the start game event is emitted when the user wants to start a game and
+ * the settings made are valid
*
* @return the event
*/
@@ -96,8 +96,9 @@ public class SettingsControl extends AbstractSettingsControl {
view.getSettingsPanel().enableRemovePlayerButtons(
Collections.nCopies(settings.getPlayerList().size(),
enableRemoveButtons));
- view.getSettingsPanel().enableAddPlayerButton(
- settings.getPlayerList().size() < ISettingsPanel.PLAYER_COLORS.length);
+ view.getSettingsPanel()
+ .enableAddPlayerButton(
+ settings.getPlayerList().size() < ISettingsPanel.PLAYER_COLORS.length);
checkSettings();
@@ -109,6 +110,10 @@ public class SettingsControl extends AbstractSettingsControl {
view.getSettingsPanel().setGameSettings(settings);
}
+ /**
+ * Aborts the settings control and emits a start game event if settings have
+ * been approved
+ */
private void startGame() {
if (!checkSettings()) {
return;