Added several comments in TurnLogic

git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@532 72836036-5685-4462-b002-a69064685172
This commit is contained in:
Bennet Gerlach 2011-06-21 02:50:06 +02:00
parent bafbd6cac1
commit 900554a09b

View file

@ -36,19 +36,43 @@ public class TurnLogic {
private int neededPoints = 0; private int neededPoints = 0;
private double neededScore = 0; private double neededScore = 0;
/**
* A Contradiction is thrown once a state is reached that isn't legal
*/
@SuppressWarnings("serial") @SuppressWarnings("serial")
private static class Contradiction extends Throwable { private static class Contradiction extends Throwable {
} }
/**
* The state the search is in, containing {@link StoneState}s
*/
private class State { private class State {
/**
* A list of all stones
*/
ArrayList<StoneState> stones = new ArrayList<StoneState>(); ArrayList<StoneState> stones = new ArrayList<StoneState>();
/**
* The stones that were changed since the previous state
*/
HashSet<Integer> changedStones = new HashSet<Integer>(); HashSet<Integer> changedStones = new HashSet<Integer>();
/**
* The position of the jokers in the other lists
*/
ArrayList<Integer> jokerIDs = new ArrayList<Integer>(); ArrayList<Integer> jokerIDs = new ArrayList<Integer>();
/**
* Create a new
*/
public State() { public State() {
} }
/**
* Create a copy of a state
*
* @param state
* the state to copy
*/
public State(State state) { public State(State state) {
for (StoneState stone : state.stones) { for (StoneState stone : state.stones) {
stones.add(new StoneState(stone)); stones.add(new StoneState(stone));
@ -56,6 +80,12 @@ public class TurnLogic {
jokerIDs = state.jokerIDs; jokerIDs = state.jokerIDs;
} }
/**
* Adds stones to be considered in the state
*
* @param stone
* the stone to add
*/
public void add(StoneState stone) { public void add(StoneState stone) {
stones.add(stone); stones.add(stone);
changedStones.add(stones.size() - 1); changedStones.add(stones.size() - 1);
@ -64,6 +94,12 @@ public class TurnLogic {
} }
} }
/**
* Update the stones to consider the changes of the changed stones
*
* @throws Contradiction
* Is thrown if the changes contradict each other
*/
public void updateStones() throws Contradiction { public void updateStones() throws Contradiction {
checkJokerCount(); checkJokerCount();
for (int i : changedStones) { for (int i : changedStones) {
@ -81,6 +117,12 @@ public class TurnLogic {
} }
} }
/**
* One step in the update process
*
* @throws Contradiction
* Is thrown if changes contradict each other
*/
public void updateStonesStep() throws Contradiction { public void updateStonesStep() throws Contradiction {
HashSet<Integer> newChangedStones = new HashSet<Integer>(); HashSet<Integer> newChangedStones = new HashSet<Integer>();
for (int i = 0; i < stoneCount; i++) { for (int i = 0; i < stoneCount; i++) {
@ -94,6 +136,12 @@ public class TurnLogic {
changedStones = newChangedStones; changedStones = newChangedStones;
} }
/**
* Returns whether the stones have a definite value and the state is thereby
* solved
*
* @return whether the state is solved
*/
public boolean isSolved() { public boolean isSolved() {
for (StoneState stone : stones) { for (StoneState stone : stones) {
if (!stone.isSolved()) { if (!stone.isSolved()) {
@ -103,6 +151,12 @@ public class TurnLogic {
return true; return true;
} }
/**
* Checks that not too many jokers are trying to be used
*
* @throws Contradiction
* Is thrown if too many jokers are trying to be used
*/
private void checkJokerCount() throws Contradiction { private void checkJokerCount() throws Contradiction {
int jokersLeft = jokerIDs.size(); int jokersLeft = jokerIDs.size();
int jokersRight = jokerIDs.size(); int jokersRight = jokerIDs.size();
@ -122,6 +176,12 @@ public class TurnLogic {
} }
} }
/**
* Checks that enough points and a high enough score are reached
*
* @throws Contradiction
* Is thrown if points are too few or score is too low
*/
public void checkScoreAndPoints() throws Contradiction { public void checkScoreAndPoints() throws Contradiction {
if (getPoints() < neededPoints) { if (getPoints() < neededPoints) {
throw new Contradiction(); throw new Contradiction();
@ -131,6 +191,11 @@ public class TurnLogic {
} }
} }
/**
* Returns the points
*
* @return the amount of points
*/
public int getPoints() { public int getPoints() {
int sum = 0; int sum = 0;
for (StoneState stone : stones) { for (StoneState stone : stones) {
@ -141,6 +206,11 @@ public class TurnLogic {
return sum; return sum;
} }
/**
* Returns the score
*
* @return the total score reached
*/
public double getScore() { public double getScore() {
double sum = 0; double sum = 0;
for (StoneState stone : stones) { for (StoneState stone : stones) {
@ -153,6 +223,10 @@ public class TurnLogic {
} }
} }
/**
* Contains the remaining possible values, colors, positions, etc. a stone can
* take and its possible neighbors in a group or run
*/
private class StoneState { private class StoneState {
int id; int id;
boolean joker; boolean joker;
@ -165,6 +239,16 @@ public class TurnLogic {
HashSet<Integer> leftGroup; HashSet<Integer> leftGroup;
HashSet<Integer> rightGroup; HashSet<Integer> rightGroup;
/**
* Creates a new
*
* @param id
* the stone's identifier
* @param stone
* the stone
* @param table
* whether is on the table
*/
public StoneState(int id, Stone stone, boolean table) { public StoneState(int id, Stone stone, boolean table) {
this.id = id; this.id = id;
joker = stone.isJoker(); joker = stone.isJoker();
@ -180,6 +264,12 @@ public class TurnLogic {
rightGroup = makeFullSet(); rightGroup = makeFullSet();
} }
/**
* Creates a copy
*
* @param stone
* the state to copy
*/
public StoneState(StoneState stone) { public StoneState(StoneState stone) {
this.id = stone.id; this.id = stone.id;
this.joker = stone.joker; this.joker = stone.joker;
@ -193,6 +283,11 @@ public class TurnLogic {
this.rightGroup = new HashSet<Integer>(stone.rightGroup); this.rightGroup = new HashSet<Integer>(stone.rightGroup);
} }
/**
* Returns a set containing all possible neighbors
*
* @return the set
*/
private HashSet<Integer> makeFullSet() { private HashSet<Integer> makeFullSet() {
HashSet<Integer> set = new HashSet<Integer>(); HashSet<Integer> set = new HashSet<Integer>();
for (int i = 0; i < stoneCount; i++) { for (int i = 0; i < stoneCount; i++) {
@ -204,11 +299,18 @@ public class TurnLogic {
return set; return set;
} }
/**
* Returns whether the recent changes affect the stone
*
* @param changes
* the changes
* @return whether the stone is affected
*/
public boolean isInterested(HashSet<Integer> changes) { public boolean isInterested(HashSet<Integer> changes) {
return !(Collections.disjoint(changes, leftRun) return !(Collections.disjoint(changes, leftRun)
&& Collections.disjoint(changes, rightRun) && Collections.disjoint(changes, rightRun)
&& Collections.disjoint(changes, leftGroup) && Collections && Collections.disjoint(changes, leftGroup) && Collections.disjoint(
.disjoint(changes, rightGroup)); changes, rightGroup));
} }
public <T extends Comparable<T>> boolean lessThan(T a, T b) { public <T extends Comparable<T>> boolean lessThan(T a, T b) {
@ -274,8 +376,7 @@ public class TurnLogic {
return a != null && b != null && a.equals(b); return a != null && b != null && a.equals(b);
} }
private void breakSymmetries(HashSet<Integer> changes) private void breakSymmetries(HashSet<Integer> changes) throws Contradiction {
throws Contradiction {
Integer mySym = symmetryBreakerValue(); Integer mySym = symmetryBreakerValue();
if (mySym == null) { if (mySym == null) {
return; return;
@ -286,8 +387,7 @@ public class TurnLogic {
} }
StoneState otherStone = top.stones.get(other); StoneState otherStone = top.stones.get(other);
if (!(joker && otherStone.joker || nonNullEquals(value, if (!(joker && otherStone.joker || nonNullEquals(value,
otherStone.value) otherStone.value) && nonNullEquals(color, otherStone.color))) {
&& nonNullEquals(color, otherStone.color))) {
continue; continue;
} }
Integer otherSym = top.stones.get(other).symmetryBreakerValue(); Integer otherSym = top.stones.get(other).symmetryBreakerValue();
@ -306,8 +406,8 @@ public class TurnLogic {
if (onTable != Boolean.TRUE) { if (onTable != Boolean.TRUE) {
return -1; return -1;
} }
if (leftRun.size() > 1 || leftGroup.size() > 1 if (leftRun.size() > 1 || leftGroup.size() > 1 || rightRun.size() > 1
|| rightRun.size() > 1 || rightGroup.size() > 1) { || rightGroup.size() > 1) {
return null; return null;
} }
int mode; int mode;
@ -347,8 +447,7 @@ public class TurnLogic {
if (!other.runNeighbor(this) || !other.rightRun.contains(id)) { if (!other.runNeighbor(this) || !other.rightRun.contains(id)) {
leftRun.remove(i); leftRun.remove(i);
changed = true; changed = true;
} else if (other.rightRun.size() == 1 } else if (other.rightRun.size() == 1 && other.onTable == Boolean.TRUE) {
&& other.onTable == Boolean.TRUE) {
changed |= leftRun.retainAll(Arrays.asList(i)); changed |= leftRun.retainAll(Arrays.asList(i));
changed |= onTable != Boolean.TRUE; changed |= onTable != Boolean.TRUE;
onTable = true; onTable = true;
@ -368,8 +467,7 @@ public class TurnLogic {
if (!this.runNeighbor(other) || !other.leftRun.contains(id)) { if (!this.runNeighbor(other) || !other.leftRun.contains(id)) {
rightRun.remove(i); rightRun.remove(i);
changed = true; changed = true;
} else if (other.leftRun.size() == 1 } else if (other.leftRun.size() == 1 && other.onTable == Boolean.TRUE) {
&& other.onTable == Boolean.TRUE) {
changed |= rightRun.retainAll(Arrays.asList(i)); changed |= rightRun.retainAll(Arrays.asList(i));
changed |= onTable != Boolean.TRUE; changed |= onTable != Boolean.TRUE;
onTable = true; onTable = true;
@ -386,8 +484,7 @@ public class TurnLogic {
relevantChanges.retainAll(changes); relevantChanges.retainAll(changes);
for (int i : relevantChanges) { for (int i : relevantChanges) {
StoneState other = top.stones.get(i); StoneState other = top.stones.get(i);
if (!other.groupNeighbor(this) if (!other.groupNeighbor(this) || !other.rightGroup.contains(id)) {
|| !other.rightGroup.contains(id)) {
leftGroup.remove(i); leftGroup.remove(i);
changed = true; changed = true;
} else if (other.rightGroup.size() == 1 } else if (other.rightGroup.size() == 1
@ -412,8 +509,7 @@ public class TurnLogic {
if (!this.groupNeighbor(other) || !other.leftGroup.contains(id)) { if (!this.groupNeighbor(other) || !other.leftGroup.contains(id)) {
rightGroup.remove(i); rightGroup.remove(i);
changed = true; changed = true;
} else if (other.leftGroup.size() == 1 } else if (other.leftGroup.size() == 1 && other.onTable == Boolean.TRUE) {
&& other.onTable == Boolean.TRUE) {
changed |= rightGroup.retainAll(Arrays.asList(i)); changed |= rightGroup.retainAll(Arrays.asList(i));
changed |= onTable != Boolean.TRUE; changed |= onTable != Boolean.TRUE;
onTable = true; onTable = true;
@ -470,9 +566,8 @@ public class TurnLogic {
private boolean checkLonelyStone() { private boolean checkLonelyStone() {
boolean changed = false; boolean changed = false;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<HashSet<Integer>> sets = Arrays.<HashSet<Integer>> asList( List<HashSet<Integer>> sets = Arrays.<HashSet<Integer>> asList(leftGroup,
leftGroup, rightGroup, leftRun, rightRun, leftGroup, rightGroup, leftRun, rightRun, leftGroup, rightGroup, leftRun);
rightGroup, leftRun);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (isNullSet(sets.get(i)) && isNullSet(sets.get(i + 1)) if (isNullSet(sets.get(i)) && isNullSet(sets.get(i + 1))
&& isNullSet(sets.get(i + 2))) { && isNullSet(sets.get(i + 2))) {
@ -506,8 +601,8 @@ public class TurnLogic {
private boolean checkStoneCanBeOnTable() throws Contradiction { private boolean checkStoneCanBeOnTable() throws Contradiction {
boolean changed = false; boolean changed = false;
if (leftGroup.isEmpty() || rightGroup.isEmpty() if (leftGroup.isEmpty() || rightGroup.isEmpty() || leftRun.isEmpty()
|| leftRun.isEmpty() || rightRun.isEmpty()) { || rightRun.isEmpty()) {
if (onTable == Boolean.TRUE) { if (onTable == Boolean.TRUE) {
throw new Contradiction(); throw new Contradiction();
} }
@ -545,8 +640,7 @@ public class TurnLogic {
} else if (isSingleNonNullSet(rightRun)) { } else if (isSingleNonNullSet(rightRun)) {
Integer value = top.stones.get(rightRun.iterator().next()).value; Integer value = top.stones.get(rightRun.iterator().next()).value;
if (value != null) { if (value != null) {
this.value = (value - 2) % settings.getHighestValue() this.value = (value - 2) % settings.getHighestValue() + 1;
+ 1;
} }
} }
changed |= this.value != null; changed |= this.value != null;
@ -574,8 +668,8 @@ public class TurnLogic {
if (onTable == null || color == null || value == null) { if (onTable == null || color == null || value == null) {
return false; return false;
} }
if (leftRun.size() > 1 || rightRun.size() > 1 if (leftRun.size() > 1 || rightRun.size() > 1 || leftGroup.size() > 1
|| leftGroup.size() > 1 || rightGroup.size() > 1) { || rightGroup.size() > 1) {
return false; return false;
} }
return true; return true;
@ -603,9 +697,8 @@ public class TurnLogic {
if (onTable != Boolean.TRUE) { if (onTable != Boolean.TRUE) {
return false; return false;
} }
for (HashSet<Integer> set : side ? Arrays for (HashSet<Integer> set : side ? Arrays.asList(leftGroup, leftRun)
.asList(leftGroup, leftRun) : Arrays.asList(rightGroup, : Arrays.asList(rightGroup, rightRun)) {
rightRun)) {
cancle: if (!set.contains(null)) { cancle: if (!set.contains(null)) {
for (int idx : set) { for (int idx : set) {
if (!top.stones.get(idx).joker) { if (!top.stones.get(idx).joker) {
@ -632,11 +725,11 @@ public class TurnLogic {
* Creates new turn logic * Creates new turn logic
* *
* @param settings * @param settings
* the game settings * the game settings
* @param tableStones * @param tableStones
* all stones on the table * all stones on the table
* @param handStones * @param handStones
* all stones on the hand * all stones on the hand
*/ */
public TurnLogic(GameSettings settings, Collection<Stone> tableStones, public TurnLogic(GameSettings settings, Collection<Stone> tableStones,
Collection<Stone> handStones) { Collection<Stone> handStones) {
@ -665,18 +758,17 @@ public class TurnLogic {
@Override @Override
public int compare(Pair<Stone, Boolean> o1, Pair<Stone, Boolean> o2) { public int compare(Pair<Stone, Boolean> o1, Pair<Stone, Boolean> o2) {
int cmp; int cmp;
cmp = ((Boolean) o1.getFirst().isJoker()).compareTo(o2 cmp = ((Boolean) o1.getFirst().isJoker()).compareTo(o2.getFirst()
.getFirst().isJoker()); .isJoker());
if (cmp != 0) { if (cmp != 0) {
return -cmp; return -cmp;
} }
cmp = (o1.getFirst().getColor()).compareTo(o2.getFirst() cmp = (o1.getFirst().getColor()).compareTo(o2.getFirst().getColor());
.getColor());
if (cmp != 0) { if (cmp != 0) {
return cmp; return cmp;
} }
cmp = ((Integer) o1.getFirst().getValue()).compareTo(o2 cmp = ((Integer) o1.getFirst().getValue()).compareTo(o2.getFirst()
.getFirst().getValue()); .getValue());
return cmp; return cmp;
} }
}); });
@ -743,8 +835,7 @@ public class TurnLogic {
ArrayList<Stone> setStones = new ArrayList<Stone>(); ArrayList<Stone> setStones = new ArrayList<Stone>();
while (true) { while (true) {
setStones.add(inputStones.get(stone.id)); setStones.add(inputStones.get(stone.id));
if (isNullSet(stone.rightRun) if (isNullSet(stone.rightRun) && isNullSet(stone.rightGroup)) {
&& isNullSet(stone.rightGroup)) {
break; break;
} }
Integer rightRunID = stone.rightRun.iterator().next(); Integer rightRunID = stone.rightRun.iterator().next();