summaryrefslogtreecommitdiffstats
path: root/src/jrummikub/model/Table.java
blob: 1f07f9765c04a0beed4166bb57bcdd630df9f9b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package jrummikub.model;

import jrummikub.util.Pair;

/** Class administering the {@link Stone}s on the game-Table */

public class Table extends StoneTray<StoneSet> 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);
		}
	}

	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<StoneSet, Position> 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;
	}

	private void splitSet(StoneSet set, Position setPosition, int stonePosition) {
		pickUp(set);

		Pair<StoneSet, StoneSet> firstSplit = set.splitAt(stonePosition);
		Pair<StoneSet, StoneSet> 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<StoneSet, Position> i : this) {
			if (!i.getFirst().isValid(gameSettings)) {
				return false;
			}
		}
		return true;
	}

}