summaryrefslogtreecommitdiffstats
path: root/src/jrummikub/model/Table.java
blob: 3fb9b5c5ed6d06271be72c8c0cf9537ed2b9177e (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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);
		}
	}

	/**
	 * 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<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;
	}

	/**
	 * 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<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;
	}

}