diff options
-rw-r--r-- | mock/jrummikub/model/MockHand.java | 11 | ||||
-rw-r--r-- | mock/jrummikub/model/MockTable.java | 11 | ||||
-rw-r--r-- | mock/jrummikub/view/MockView.java | 7 | ||||
-rw-r--r-- | src/jrummikub/control/RoundControl.java | 93 | ||||
-rw-r--r-- | src/jrummikub/control/turn/HumanTurnControl.java | 2 | ||||
-rw-r--r-- | src/jrummikub/model/IStoneTray.java | 2 | ||||
-rw-r--r-- | src/jrummikub/model/StoneTray.java | 11 | ||||
-rw-r--r-- | src/jrummikub/view/IView.java | 42 | ||||
-rw-r--r-- | src/jrummikub/view/impl/HandPanel.java | 3 | ||||
-rw-r--r-- | src/jrummikub/view/impl/StoneCollectionPanel.java | 3 | ||||
-rw-r--r-- | src/jrummikub/view/impl/StonePainter.java | 79 | ||||
-rw-r--r-- | src/jrummikub/view/impl/TablePanel.java | 14 | ||||
-rw-r--r-- | src/jrummikub/view/impl/View.java | 5 |
13 files changed, 183 insertions, 100 deletions
diff --git a/mock/jrummikub/model/MockHand.java b/mock/jrummikub/model/MockHand.java index 13f6450..d282234 100644 --- a/mock/jrummikub/model/MockHand.java +++ b/mock/jrummikub/model/MockHand.java @@ -92,4 +92,15 @@ public class MockHand implements IHand { public int getIdenticalStoneCount() { return 0; } + + @Override + public boolean contains(Stone object) { + for (Pair<Stone, Position> stone : stones) { + if (stone.getFirst() == object) { + return true; + } + } + + return false; + } } diff --git a/mock/jrummikub/model/MockTable.java b/mock/jrummikub/model/MockTable.java index 295321c..77652a6 100644 --- a/mock/jrummikub/model/MockTable.java +++ b/mock/jrummikub/model/MockTable.java @@ -69,4 +69,15 @@ public class MockTable implements ITable { return sets.size(); } + @Override + public boolean contains(StoneSet object) { + for (Pair<StoneSet, Position> set : sets) { + if (set.getFirst() == object) { + return true; + } + } + + return false; + } + } diff --git a/mock/jrummikub/view/MockView.java b/mock/jrummikub/view/MockView.java index 7329907..167bc0b 100644 --- a/mock/jrummikub/view/MockView.java +++ b/mock/jrummikub/view/MockView.java @@ -5,6 +5,7 @@ import java.io.File; import java.util.Collection; import jrummikub.model.Stone; +import jrummikub.model.StoneSet; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.MockEvent; @@ -237,4 +238,10 @@ public class MockView implements IView { } + @Override + public void setInvalidStoneSets(Collection<StoneSet> sets) { + // TODO Auto-generated method stub + + } + } diff --git a/src/jrummikub/control/RoundControl.java b/src/jrummikub/control/RoundControl.java index 930d861..174cc9a 100644 --- a/src/jrummikub/control/RoundControl.java +++ b/src/jrummikub/control/RoundControl.java @@ -50,9 +50,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 */ public RoundControl(IRoundState roundState, IView view) { this.roundState = roundState; @@ -129,12 +129,11 @@ public class RoundControl { } view.getTablePanel().setStoneSets(clonedTable.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()); if (!isHuman) startTurn(); @@ -160,11 +159,10 @@ public class RoundControl { view.getPlayerPanel().setEndTurnMode(turnMode); } turnControl = TurnControlFactory.getFactory( - roundState.getActivePlayer().getPlayerSettings().getType()) - .create(); + roundState.getActivePlayer().getPlayerSettings().getType()).create(); turnControl.setup(new ITurnControl.TurnInfo(clonedTable, clonedHand, - roundState.getActivePlayer().getLaidOut(), turnMode), - roundState.getGameSettings(), view); + roundState.getActivePlayer().getLaidOut(), turnMode), roundState + .getGameSettings(), view); turnControl.getEndOfTurnEvent().add(new IListener() { @Override public void handle() { @@ -184,10 +182,8 @@ public class RoundControl { 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)); } } } @@ -198,13 +194,11 @@ public class RoundControl { int totalValue = 0; for (StoneSet set : newSets) { - totalValue += set.classify(roundState.getGameSettings()) - .getSecond(); + totalValue += set.classify(roundState.getGameSettings()).getSecond(); } return totalValue == 0 - || totalValue >= roundState.getGameSettings() - .getInitialMeldThreshold(); + || totalValue >= roundState.getGameSettings().getInitialMeldThreshold(); } private void endOfTurn() { @@ -223,26 +217,46 @@ public class RoundControl { if (lastTurnNotEnoughPoints) { view.setInitialMeldError(roundState.getGameSettings() .getInitialMeldThreshold()); + view.setInvalidStoneSets(tableSetDifference(roundState.getTable(), + clonedTable)); } else if (lastTurnMeldError) { view.setInitialMeldFirstError(); + view.setInvalidStoneSets(touchedStoneSets()); } else { - List<Stone> markedStones = new ArrayList<Stone>(); - for (Pair<StoneSet, Position> set : clonedTable) { - if (set.getFirst().isValid(roundState.getGameSettings())) { - continue; - } - for (Stone stone : set.getFirst()) { - markedStones.add(stone); - } - } view.setStoneCollectionHidden(true); - view.setSelectedStones(markedStones); + view.setInvalidStoneSets(invalidStoneSets()); } } } + private List<StoneSet> invalidStoneSets() { + List<StoneSet> invalidSets = new ArrayList<StoneSet>(); + for (Pair<StoneSet, Position> set : clonedTable) { + if (set.getFirst().isValid(roundState.getGameSettings())) { + continue; + } + invalidSets.add(set.getFirst()); + } + return invalidSets; + } + + private List<StoneSet> touchedStoneSets() { + List<StoneSet> touchedSets = new ArrayList<StoneSet>(); + for (StoneSet set : tableSetDifference(roundState.getTable(), clonedTable)) { + for (Stone stone : set) { + if (!roundState.getActivePlayer().getHand().contains(stone)) { + touchedSets.add(set); + break; + } + } + } + + return touchedSets; + } + private void nextPlayer() { view.setSelectedStones(Collections.<Stone> emptyList()); + view.setInvalidStoneSets(Collections.<StoneSet> emptyList()); view.setStoneCollectionHidden(false); if (roundState.getLastPlayer() == null) { if (roundState.getGameHeap().getSize() == 0) { @@ -273,8 +287,7 @@ public class RoundControl { } if (!roundState.getActivePlayer().getLaidOut()) { // Player touched forbidden stones - if (!tableSetDifference(clonedTable, roundState.getTable()) - .isEmpty()) { + if (!tableSetDifference(clonedTable, roundState.getTable()).isEmpty()) { rejectMove(); lastTurnMeldError = true; return false; @@ -285,8 +298,7 @@ public class RoundControl { return false; } } - Set<Stone> tableDiff = tableDifference(roundState.getTable(), - clonedTable); + Set<Stone> tableDiff = tableDifference(roundState.getTable(), clonedTable); roundState.setTable(clonedTable); @@ -303,8 +315,7 @@ public class RoundControl { } private void rejectMove() { - Set<Stone> tableDiff = tableDifference(roundState.getTable(), - clonedTable); + Set<Stone> tableDiff = tableDifference(roundState.getTable(), clonedTable); // deal penalty, reset roundState.getGameHeap().putBack(tableDiff); dealPenalty(tableDiff.size()); @@ -398,12 +409,10 @@ 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; @@ -425,8 +434,8 @@ public class RoundControl { private static Pair<Integer, Integer> updateBestScore( Pair<Integer, Integer> bestScore, int stonePoints, int size) { if (bestScore.getFirst() == stonePoints) { - return new Pair<Integer, Integer>(stonePoints, Math.min(bestScore - .getSecond(), size)); + return new Pair<Integer, Integer>(stonePoints, Math.min( + bestScore.getSecond(), size)); } else if (bestScore.getFirst() < stonePoints) { return new Pair<Integer, Integer>(stonePoints, size); } diff --git a/src/jrummikub/control/turn/HumanTurnControl.java b/src/jrummikub/control/turn/HumanTurnControl.java index 447c44d..a9a73d7 100644 --- a/src/jrummikub/control/turn/HumanTurnControl.java +++ b/src/jrummikub/control/turn/HumanTurnControl.java @@ -441,7 +441,7 @@ public class HumanTurnControl extends AbstractTurnControl { private void endOfTurn(boolean redeal) { cleanUp(); - view.setSelectedStones(new ArrayList<Stone>()); + view.setSelectedStones(Collections.<Stone> emptyList()); if (redeal) { redealEvent.emit(); } else { diff --git a/src/jrummikub/model/IStoneTray.java b/src/jrummikub/model/IStoneTray.java index d411c9e..437ecda 100644 --- a/src/jrummikub/model/IStoneTray.java +++ b/src/jrummikub/model/IStoneTray.java @@ -55,4 +55,6 @@ public interface IStoneTray<E extends Sizeable> extends */
public int getSize();
+ public boolean contains(E object);
+
}
\ No newline at end of file diff --git a/src/jrummikub/model/StoneTray.java b/src/jrummikub/model/StoneTray.java index aaedaad..9148934 100644 --- a/src/jrummikub/model/StoneTray.java +++ b/src/jrummikub/model/StoneTray.java @@ -189,7 +189,16 @@ public class StoneTray<E extends Sizeable> implements IStoneTray<E> { */ @Override public Position getPosition(E object) { - return objects.get(object).getSecond(); + Pair<E, Position> entry = objects.get(object); + if (entry == null) { + return null; + } + return entry.getSecond(); + } + + @Override + public boolean contains(E object) { + return objects.containsKey(objects); } @Override diff --git a/src/jrummikub/view/IView.java b/src/jrummikub/view/IView.java index b84e366..b127377 100644 --- a/src/jrummikub/view/IView.java +++ b/src/jrummikub/view/IView.java @@ -5,6 +5,7 @@ import java.io.File; import java.util.Collection; import jrummikub.model.Stone; +import jrummikub.model.StoneSet; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; @@ -236,23 +237,6 @@ public interface IView { */ public void showGameListPanel(boolean show); - /** - * Different types of bottom panels - */ - public enum BottomPanelType { - /** */ - START_GAME_PANEL, - /** */ - START_TURN_PANEL, - /** */ - INVALID_TURN_PANEL, - /** */ - HUMAN_HAND_PANEL, - /** */ - COMPUTER_HAND_PANEL, - /** */ - WIN_PANEL - } /** * Is set if a player tried to lay out less than initial meld threshold @@ -260,18 +244,36 @@ public interface IView { * @param points * initial meld threshold */ - void setInitialMeldError(int points); + public void setInitialMeldError(int points); /** * Show stone collection * * @param enable */ - void setStoneCollectionHidden(boolean enable); + public void setStoneCollectionHidden(boolean enable); /** * Is set if the player tried to modify the table without laying out first */ - void setInitialMeldFirstError(); + public void setInitialMeldFirstError(); + public void setInvalidStoneSets(Collection<StoneSet> sets); + /** + * Different types of bottom panels + */ + public enum BottomPanelType { + /** */ + START_GAME_PANEL, + /** */ + START_TURN_PANEL, + /** */ + INVALID_TURN_PANEL, + /** */ + HUMAN_HAND_PANEL, + /** */ + COMPUTER_HAND_PANEL, + /** */ + WIN_PANEL + } } diff --git a/src/jrummikub/view/impl/HandPanel.java b/src/jrummikub/view/impl/HandPanel.java index 75d424a..823ca12 100644 --- a/src/jrummikub/view/impl/HandPanel.java +++ b/src/jrummikub/view/impl/HandPanel.java @@ -20,6 +20,7 @@ import jrummikub.model.Position; import jrummikub.model.Stone; import jrummikub.util.Pair; import jrummikub.view.IHandPanel; +import jrummikub.view.impl.StonePainter.StoneState; /** * Implementation of the board @@ -118,7 +119,7 @@ class HandPanel extends AbstractStonePanel implements IHandPanel { for (Pair<Stone, Position> entry : getStones()) { getStonePainter().paintStone(g, entry.getFirst(), entry.getSecond(), - selectedStones.contains(entry.getFirst()), + selectedStones.contains(entry.getFirst()) ? StoneState.SELECTED : StoneState.NORMAL, entry.getFirst() == getHoveredStone()); } } diff --git a/src/jrummikub/view/impl/StoneCollectionPanel.java b/src/jrummikub/view/impl/StoneCollectionPanel.java index 5b08f51..1bb21a9 100644 --- a/src/jrummikub/view/impl/StoneCollectionPanel.java +++ b/src/jrummikub/view/impl/StoneCollectionPanel.java @@ -20,6 +20,7 @@ import jrummikub.util.Event1; import jrummikub.util.IEvent1; import jrummikub.util.Pair; import jrummikub.view.IStoneCollectionPanel; +import jrummikub.view.impl.StonePainter.StoneState; /** * Implementation of the stone collection (selection) @@ -148,7 +149,7 @@ class StoneCollectionPanel extends AbstractStonePanel implements float xpos = 0; for (Stone stone : selectedStones) { - getStonePainter().paintStone(g, stone, new Position(xpos, 0), false, + getStonePainter().paintStone(g, stone, new Position(xpos, 0), StoneState.NORMAL, stone == getHoveredStone()); xpos++; } diff --git a/src/jrummikub/view/impl/StonePainter.java b/src/jrummikub/view/impl/StonePainter.java index 298f9ac..143ef86 100644 --- a/src/jrummikub/view/impl/StonePainter.java +++ b/src/jrummikub/view/impl/StonePainter.java @@ -23,6 +23,10 @@ import jrummikub.model.StoneColor; * coordinates */ class StonePainter { + enum StoneState { + NORMAL, SELECTED, INVALID + } + private static final double ASPECT_RATIO = 0.75f; private static final double DEFAULT_WIDTH = 40; private static final double TEXT_POS = 0.275f; @@ -34,11 +38,10 @@ class StonePainter { private static final double BRIGHTER_SCALE = 1.15f; private static final double HOVER_RATIO = 0.7f; + private static final double REDDEN_RATIO = 0.3f; - private Map<StoneColor, Map<Integer, BufferedImage>> defaultStones; - private Map<StoneColor, Map<Integer, BufferedImage>> selectedStones; - private Map<StoneColor, Map<Integer, BufferedImage>> hoveredStones; - private Map<StoneColor, Map<Integer, BufferedImage>> hoveredSelectedStones; + private Map<StoneState, Map<StoneColor, Map<Integer, BufferedImage>>> defaultStones; + private Map<StoneState, Map<StoneColor, Map<Integer, BufferedImage>>> hoveredStones; /** * The width of one pixel in the scale of 1.0 @@ -71,6 +74,14 @@ class StonePainter { return new Color(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b); } + private static Color redden(Color color) { + int r = (int) (color.getRed() * REDDEN_RATIO + 255 * (1 - REDDEN_RATIO)); + int g = (int) (color.getGreen() * REDDEN_RATIO + 128 * (1 - REDDEN_RATIO)); + int b = (int) (color.getBlue() * REDDEN_RATIO + 128 * (1 - REDDEN_RATIO)); + + return new Color(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b); + } + public static Color getColor(StoneColor color) { switch (color) { case BLACK: @@ -160,21 +171,13 @@ class StonePainter { } private BufferedImage getStoneImage(StoneColor color, int value, - boolean selected, boolean hovered) { + StoneState state, boolean hovered) { Map<StoneColor, Map<Integer, BufferedImage>> stoneMap; - if (selected) { - if (hovered) { - stoneMap = hoveredSelectedStones; - } else { - stoneMap = selectedStones; - } + if (hovered) { + stoneMap = hoveredStones.get(state); } else { - if (hovered) { - stoneMap = hoveredStones; - } else { - stoneMap = defaultStones; - } + stoneMap = defaultStones.get(state); } BufferedImage image = stoneMap.get(color).get(value); @@ -182,10 +185,15 @@ class StonePainter { if (image == null) { Color background = BACKGROUND_COLOR; Color foreground = getColor(color); - if (selected) { + + if (state == StoneState.SELECTED) { background = background.darker(); foreground = foreground.darker(); + } else if (state == StoneState.INVALID) { + background = redden(background); + foreground = redden(foreground); } + if (hovered) { background = hover(background); foreground = hover(foreground); @@ -200,16 +208,20 @@ class StonePainter { } private void resetPrepaint() { - defaultStones = new HashMap<StoneColor, Map<Integer, BufferedImage>>(); - selectedStones = new HashMap<StoneColor, Map<Integer, BufferedImage>>(); - hoveredStones = new HashMap<StoneColor, Map<Integer, BufferedImage>>(); - hoveredSelectedStones = new HashMap<StoneColor, Map<Integer, BufferedImage>>(); - - for (StoneColor color : StoneColor.values()) { - defaultStones.put(color, new HashMap<Integer, BufferedImage>()); - selectedStones.put(color, new HashMap<Integer, BufferedImage>()); - hoveredStones.put(color, new HashMap<Integer, BufferedImage>()); - hoveredSelectedStones.put(color, new HashMap<Integer, BufferedImage>()); + defaultStones = new HashMap<StoneState, Map<StoneColor, Map<Integer, BufferedImage>>>(); + hoveredStones = new HashMap<StoneState, Map<StoneColor, Map<Integer, BufferedImage>>>(); + + for (StoneState state : StoneState.values()) { + Map<StoneColor, Map<Integer, BufferedImage>> defaultStateStones = new HashMap<StoneColor, Map<Integer, BufferedImage>>(); + Map<StoneColor, Map<Integer, BufferedImage>> hoveredStateStones = new HashMap<StoneColor, Map<Integer, BufferedImage>>(); + + defaultStones.put(state, defaultStateStones); + hoveredStones.put(state, hoveredStateStones); + + for (StoneColor color : StoneColor.values()) { + defaultStateStones.put(color, new HashMap<Integer, BufferedImage>()); + hoveredStateStones.put(color, new HashMap<Integer, BufferedImage>()); + } } } @@ -348,25 +360,26 @@ class StonePainter { * the stone to paint * @param p * the position of the stone - * @param selected - * if selected is true the stone will be painted darker + * @param state + * if the stone is selected the stone will be painted darker, if it + * is invalid it will be painted in red * @param hovered * if hovered is true the stone will be painted brighter */ public void paintStone(Graphics2D g, Stone stone, Position p, - boolean selected, boolean hovered) { + StoneState state, boolean hovered) { int width = getStoneWidth(); int height = getStoneHeight(); int x = (int) Math.round(p.getX() * width), y = (int) Math.round(p.getY() * height); if (stone.isJoker()) { - g.drawImage(getStoneImage(stone.getColor(), 0, selected, hovered), x, y, + g.drawImage(getStoneImage(stone.getColor(), 0, state, hovered), x, y, null); } else { g.drawImage( - getStoneImage(stone.getColor(), stone.getValue(), selected, hovered), - x, y, null); + getStoneImage(stone.getColor(), stone.getValue(), state, hovered), x, + y, null); } } } diff --git a/src/jrummikub/view/impl/TablePanel.java b/src/jrummikub/view/impl/TablePanel.java index 1e8a2b6..4b7ab9f 100644 --- a/src/jrummikub/view/impl/TablePanel.java +++ b/src/jrummikub/view/impl/TablePanel.java @@ -28,6 +28,7 @@ import jrummikub.util.IListener1; import jrummikub.util.Pair; import jrummikub.view.IStoneCollectionPanel; import jrummikub.view.ITablePanel; +import jrummikub.view.impl.StonePainter.StoneState; /** * The implementation of the table @@ -54,6 +55,8 @@ class TablePanel extends AbstractStonePanel implements ITablePanel { private Iterable<Pair<StoneSet, Position>> stoneSets = Collections.emptySet(); private List<Pair<StoneSet, Position>> pauseStoneSets; + private Collection<StoneSet> invalidStoneSets = Collections.emptyList(); + private Collection<Stone> selectedStones = Collections.emptyList(); private Event1<StoneSet> leftConnectorClickEvent = new Event1<StoneSet>(); @@ -112,6 +115,11 @@ class TablePanel extends AbstractStonePanel implements ITablePanel { repaint(); } + void setInvalidStoneSets(Collection<StoneSet> sets) { + invalidStoneSets = sets; + repaint(); + } + void createPauseStoneSets() { pauseStoneSets = new ArrayList<Pair<StoneSet, Position>>(); @@ -312,8 +320,12 @@ class TablePanel extends AbstractStonePanel implements ITablePanel { (int) (width * CONNECTOR_WIDTH), height))); for (Stone stone : stoneSet) { + StoneState state = invalidStoneSets.contains(stoneSet) ? StoneState.INVALID + : selectedStones.contains(stone) ? StoneState.SELECTED + : StoneState.NORMAL; + getStonePainter().paintStone(g, stone, new Position(x, pos.getY()), - selectedStones.contains(stone), stone == getHoveredStone()); + state, stone == getHoveredStone()); x++; } diff --git a/src/jrummikub/view/impl/View.java b/src/jrummikub/view/impl/View.java index 83ca40b..5ede7b3 100644 --- a/src/jrummikub/view/impl/View.java +++ b/src/jrummikub/view/impl/View.java @@ -365,6 +365,11 @@ public class View extends JFrame implements IView { } @Override + public void setInvalidStoneSets(Collection<StoneSet> sets) { + table.setInvalidStoneSets(sets); + } + + @Override public void showSettingsPanel(boolean show) { if (show) { settingsPanel.resetTabbedPane(); |