package jrummikub.model; import jrummikub.util.Pair; /** Class administering the {@link Stone}s on the game-Table */ public class Table extends StoneTray implements ITable { private static final long serialVersionUID = 2433091681355019937L; private GameSettings gameSettings; private static class StoneInfo { StoneSet set; Position setPosition; int stonePosition; public StoneInfo(StoneSet set, Position setPosition, int stonePosition) { this.set = set; this.setPosition = setPosition; this.stonePosition = stonePosition; } } /** * Constructor for a table * * @param settings * GameSettings */ public Table(GameSettings settings) { gameSettings = settings; } /** * Removes {@link Stone} from the Table * * @param stone * stone to pick up */ @Override public void pickUpStone(Stone stone) { StoneInfo info = findStoneInfo(stone); if (info != null) { splitSet(info.set, info.setPosition, info.stonePosition); } } /** * Finds {@link StoneInfo} * * @param stone * the stone * @return the info */ private StoneInfo findStoneInfo(Stone stone) { // Find the set of the stone StoneInfo info; StoneSet set = null; Position setPosition = null; int stonePosition = 0; setLoop: for (Pair i : this) { set = i.getFirst(); setPosition = i.getSecond(); stonePosition = 0; for (Stone j : set) { if (j == stone) { break setLoop; } stonePosition++; } set = null; } // Stone not found if (set == null) { info = null; } else { info = new StoneInfo(set, setPosition, stonePosition); } return info; } @Override public StoneSet findStoneSet(Stone stone) { StoneInfo info = findStoneInfo(stone); if (info == null) { return null; } return info.set; } /** * Splits a stone set at a specified position * * @param set * the stone set to split * @param setPosition * the set's position on the table * @param stonePosition * the stone after which splitting should occur */ private void splitSet(StoneSet set, Position setPosition, int stonePosition) { pickUp(set); Pair firstSplit = set.splitAt(stonePosition); Pair secondSplit = firstSplit.getSecond() .splitAt(1); StoneSet leftSet = firstSplit.getFirst(); StoneSet rightSet = secondSplit.getSecond(); if (set.classify(gameSettings).getFirst() == StoneSet.Type.RUN) { Position leftPosition, rightPosition; leftPosition = setPosition; rightPosition = new Position( setPosition.getX() + stonePosition + 1, setPosition.getY()); drop(leftSet, leftPosition); drop(rightSet, rightPosition); } else { Position newPosition = new Position(setPosition.getX() + 0.5f, setPosition.getY()); if (leftSet == null) { drop(rightSet, newPosition); } else if (rightSet == null) { drop(leftSet, newPosition); } else { drop(leftSet.join(rightSet), newPosition); } } } /** Tests the Table for rule conflicts by checking all the {@link StoneSet} */ @Override public boolean isValid() { for (Pair i : this) { if (!i.getFirst().isValid(gameSettings)) { return false; } } return true; } }