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:
parent
bafbd6cac1
commit
900554a09b
1 changed files with 130 additions and 39 deletions
|
@ -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();
|
||||||
|
|
Reference in a new issue