package jrummikub.model; import static jrummikub.model.StoneTray.Direction.LEFT; import static jrummikub.model.StoneTray.Direction.RIGHT; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.TreeMap; import jrummikub.ai.TurnLogic; import jrummikub.util.Pair; /** Class managing a {@link Player}'s {@link Stone}s */ public class Hand extends StoneTray implements IHand { private static final long serialVersionUID = 192210056255744909L; /** * The width of the hand */ public final static int WIDTH = 14; @Override public int getFreeRowSpace(int row) { int count = 0; for (Pair entry : this) { if (entry.getSecond().getY() == row) { count++; } } return WIDTH - count; } @Override public int getRowCount() { int rows = 0; for (Pair entry : this) { if (entry.getSecond().getY() > rows) { rows = (int) entry.getSecond().getY(); } } return rows + 1; } @Override protected Pair fixInvalidDrop(Stone stone, Position pos, Direction dir) { double x = pos.getX(); double y = pos.getY(); if (x >= 0 && x <= WIDTH - 1) { return null; } if (x < 0) { return new Pair(new Position(0, y), RIGHT); } else { if (getFreeRowSpace((int) y) == 0) { return new Pair(new Position(0, y + 1), RIGHT); } else { return new Pair( new Position(WIDTH - 1, y), LEFT); } } } @Override public int getStonePoints(GameSettings settings) { int points = 0; for (Pair entry : this) { if (entry.getFirst().isJoker()) { points += settings.getJokerPoints(); } else { points += entry.getFirst().getValue(); } } return points; } @Override public boolean isInitialMeldPossible(GameSettings settings) { List handStones = new ArrayList(); for (Pair entry : this) { handStones.add(entry.getFirst()); } TurnLogic turnLogic = new TurnLogic(settings, Collections. emptyList(), handStones); turnLogic.needIntialMeldThreshold(); return turnLogic.solve(); } private static void incrementStoneCount( TreeMap, Integer> stones, Pair stone) { if (stones.containsKey(stone)) { stones.put(stone, stones.get(stone) + 1); } else { stones.put(stone, 1); } } private final static Comparator> comparator = new Comparator>() { @Override public int compare(Pair o1, Pair o2) { int firstComparison = o1.getFirst().compareTo(o2.getFirst()); if (firstComparison != 0) { return -firstComparison; } else { return o1.getSecond().compareTo(o2.getSecond()); } } }; /** * Counts the numbers of stones * * @param stones * the stones to count * @return the numbers for all stones */ private static Pair, Integer>, Integer> countStones( List stones) { int jokerCount = 0; TreeMap, Integer> stoneCounts = new TreeMap, Integer>( comparator); for (Stone stone : stones) { if (stone.isJoker()) { jokerCount++; } else { Pair key = new Pair( stone.getValue(), stone.getColor()); incrementStoneCount(stoneCounts, key); } } return new Pair, Integer>, Integer>( stoneCounts, jokerCount); } @Override public int getIdenticalStoneCount() { List stones = new ArrayList(); for (Iterator> iter = this.iterator(); iter .hasNext();) { stones.add(iter.next().getFirst()); } Pair, Integer>, Integer> stoneCounts = countStones(stones); int pairCount = 0; for (int count : stoneCounts.getFirst().values()) { pairCount += count / 2; } return pairCount; } }