Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion puzzles files/lightup/Goal Conditions/prove cell must be
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Legup version="2.0.0">
<puzzle name="LightUp" tag="69495">
<board height="3" width="3">
<goal type="PROVE_CELL_MUST_BE" assumeSolution="true">
<goal type="PROVE_CELL_MUST_BE">
<cell value="-3" x="1" y="0"/>
<cell value="-4" x="2" y="0"/>
</goal>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@ public enum SelectionMode {
protected ElementButton prevButton;
private SelectionMode selectionMode;
private Object goalValueData;
private boolean assumeSolution;

public EditorElementController() {
super();
elementController = null;
prevButton = null;
selectionMode = SelectionMode.PLACEABLE;
goalValueData = null;
assumeSolution = false;
}

/**
Expand Down Expand Up @@ -76,13 +74,6 @@ public void setGoalDataType(PlaceableElement elementType) {
}
}

public void setAssumeSolution(boolean assume) {
if (elementController != null) {
assumeSolution = assume;
elementController.setAssumeSolution(assume);
}
}

/**
* Handles the event when a button associated with an Element is pressed
*
Expand Down
8 changes: 0 additions & 8 deletions src/main/java/edu/rpi/legup/controller/ElementController.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public class ElementController
private GoalType currentGoalType;
private PlaceableElement currentGoalValue;
private Object goalValueData;
private boolean assumeSolution;

/**
* ElementController Constructor controller to handle ui events associated interacting with a
Expand All @@ -54,7 +53,6 @@ public ElementController() {
this.currentGoalType = GoalType.DEFAULT;
this.currentGoalValue = null;
this.goalValueData = null;
this.assumeSolution = false;
}

/**
Expand Down Expand Up @@ -105,12 +103,6 @@ public PlaceableElement getCurrentGoalValue() {
return this.currentGoalValue;
}

public void setAssumeSolution(boolean assume) {
this.assumeSolution = assume;
Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule();
puzzle.getGoal().setAssumeSolution(assume);
}

/**
* Sets the {@link BoardView}
*
Expand Down
62 changes: 10 additions & 52 deletions src/main/java/edu/rpi/legup/model/Goal.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,17 @@
public class Goal {
private ArrayList<GridCell> cellList;
private final GoalType goalType;
private boolean assumeSolution;

/**
* Constructs a Goal object with an empty cell list with no assumed solution
* Constructs a Goal object with an empty cell list
*
* @param goalType type of goal
*/
public Goal(GoalType goalType) {
this.cellList = new ArrayList<>();
this.goalType = goalType;
this.assumeSolution = false;
}

/**
* Constructs a Goal object with an empty cell list
*
* @param goalType type of goal
* @param assume whether to assume there is a solution to the puzzle
*/
public Goal(GoalType goalType, boolean assume) {
this.cellList = new ArrayList<>();
this.goalType = goalType;
this.assumeSolution = assume;
}

/**
* Constructs a Goal object only requiring a given cell
Expand All @@ -53,7 +40,6 @@ public Goal(GridCell cell, GoalType goalType) {
cellList.add(cell);
}
this.goalType = goalType;
this.assumeSolution = false;
}

/**
Expand Down Expand Up @@ -82,24 +68,6 @@ public GoalType getType() {
return goalType;
}

/**
* Get the value of assumeSolution
*
* @return assumeSolution
*/
public boolean assumeSolution() {
return assumeSolution;
}

/**
* Set the value of assumeSolution
*
* @param assume whether to assume there is a solution to the puzzle
*/
public void setAssumeSolution(boolean assume) {
assumeSolution = assume;
}

/**
* Creates tool tip text for a cell being hovered over.
*
Expand Down Expand Up @@ -147,19 +115,11 @@ public String getGoalText() {
}

String text = "Prove ";
if (assumeSolution) {
text += "that if there is a solution, then ";
}
return switch (goalType) {
case GoalType.PROVE_CELL_MUST_BE ->
text
+ getValueSeparatedGoalText(" is forced to be ", " are forced to be ")
+ ".";
case GoalType.PROVE_CELL_MIGHT_NOT_BE ->
text
+ getValueSeparatedGoalText(
" is not forced to be ", " are not forced to be ")
+ ".";
return switch(goalType) {
case GoalType.PROVE_CELL_MUST_BE -> text + getValueSeparatedGoalText(
" is forced to be ", " are forced to be ") + ".";
case GoalType.PROVE_CELL_MIGHT_NOT_BE -> text + getValueSeparatedGoalText(
" is not forced to be ", " are not forced to be ") + ".";
case GoalType.PROVE_SINGLE_CELL_VALUE -> {
text += (cellList.size() > 1 ? "cells " : "cell ");
text += concatCellLocs(cellList);
Expand All @@ -174,12 +134,10 @@ public String getGoalText() {
}
case GoalType.PROVE_ANY_SOLUTION -> "Find any solution to the puzzle.";
case GoalType.PROVE_NO_SOLUTION -> "Prove that there are no solutions to the puzzle.";
case GoalType.PROVE_VALUES_ARE_POSSIBLE ->
text + getValueSeparatedGoalText(" can be ", " can be ") + " at the same time.";
case GoalType.PROVE_VALUES_ARE_IMPOSSIBLE ->
text
+ getValueSeparatedGoalText(" cannot be ", " cannot be ")
+ " at the same time";
case GoalType.PROVE_VALUES_ARE_POSSIBLE -> text + getValueSeparatedGoalText(
" can be ", " can be ") + (cellList.size() > 1? " at the same time." : ".");
case GoalType.PROVE_VALUES_ARE_IMPOSSIBLE -> text + getValueSeparatedGoalText(
" cannot be ", " cannot be ") + (cellList.size() > 1? " at the same time." : ".");

default -> "Unrecognized goal condition.";
};
Expand Down
28 changes: 11 additions & 17 deletions src/main/java/edu/rpi/legup/model/GoalNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,17 @@ been closed by a contradiction rule, verus an "open" one that has not. A "comple
one whose board holds a valid, proven solution to the puzzle, versus an "incomplete" leaf that
has not.

Any goal type that refers to "assuming a solution exists" can have an additional field specified
in the xml goal element (assumeSolution="true"). This will allow for the proof to be shortened, and
change the text of the goal to "Prove that if there is a solution, then...". This defaults to false
if the field is not present. It is not accounted for in other goalTypes, where it either wouldn't
make a difference (i.e. PROVE_MULTIPLE_CELL_VALUE) or would make no sense (i.e. PROVE_NO_SOLUTION)

| **GoalType** | **Goal** | **Conditions of proof tree** |
|---------------------------------|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|
| **DEFAULT** | Prove all possible solutions, or prove none exist | Every open leaf is a complete one |
| **PROVE_ANY_SOLUTION** | Prove any solution | There is a complete leaf |
| **PROVE_NO_SOLUTION** | Prove that there is no solution to the puzzle | There are no open leaves |
| **PROVE_CELL_MUST_BE** | Prove that the given cell locations are forced into the given set of values | All open leaves are proven to match the set, and one solution is proven / assumed to exist |
| **PROVE_CELL_MIGHT_NOT_BE** | Prove that the given cell locations are not forced into have the given set of values | Either:<br/> Any complete leaf has a different set of values<br/> Every open leaf has a different set of values |
| **PROVE_SINGLE_CELL_VALUE** | Prove that the given cell locations are forced into one set of values | The set of values at the goal locations are proven to match in every open branch, and one solution is proven / assumed to exist |
| **PROVE_MULTIPLE_CELL_VALUE** | Prove that the given cell locations are not forced into one set of values | The set of values at the goal locations are proven to match in at least two complete leaves |
| **PROVE_VALUES_ARE_POSSIBLE** | Prove that the given cell locations are able to have the given set of values | Either:<br/>Any complete leaf matches the set<br/>Every open leaf matches the set and a solution is assumed to exist |
| **PROVE_VALUES_ARE_IMPOSSIBLE** | Prove that the given cell locations are not able to have the given set of values | Every open leaf has a different set of values |
| **GoalType** | **Goal** | **Conditions of proof tree** |
|---------------------------------|--------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| **DEFAULT** | Prove all possible solutions, or prove none exist | Every open leaf is a complete one |
| **PROVE_ANY_SOLUTION** | Prove any solution | There is a complete leaf |
| **PROVE_NO_SOLUTION** | Prove that there is no solution to the puzzle | There are no open leaves |
| **PROVE_CELL_MUST_BE** | Prove that the given cell locations are forced into the given set of values | All open leaves are proven to match the set |
| **PROVE_CELL_MIGHT_NOT_BE** | Prove that the given cell locations are not forced into have the given set of values | Either:<br/> Any complete leaf has a different set of values<br/> Every open leaf has a different set of values |
| **PROVE_SINGLE_CELL_VALUE** | Prove that the given cell locations are forced into one set of values | The set of values at the goal locations are proven to match in every open branch |
| **PROVE_MULTIPLE_CELL_VALUE** | Prove that the given cell locations are not forced into one set of values | The set of values at the goal locations are proven to match in at least two complete leaves |
| **PROVE_VALUES_ARE_POSSIBLE** | Prove that the given cell locations are able to have the given set of values | Either:<br/>Any complete leaf matches the set<br/>Every open leaf matches the set |
| **PROVE_VALUES_ARE_IMPOSSIBLE** | Prove that the given cell locations are not able to have the given set of values | Every open leaf has a different set of values |


## Extending to New Puzzles
Expand Down
23 changes: 10 additions & 13 deletions src/main/java/edu/rpi/legup/model/Puzzle.java
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,10 @@ public boolean isPuzzleComplete() {
return false;
}

// If the puzzle has no solution, this is a logical contradiction from which every
// claim can be derived
if (getOpenLeaves().isEmpty()) {return true;}

// The goal determines what state the leaves must be in.
return switch (this.goal.getType()) {
case PROVE_CELL_MUST_BE -> {
Expand All @@ -366,8 +370,7 @@ public boolean isPuzzleComplete() {
yield false;
}
}
// There must be a proven solution
yield (goal.assumeSolution() || !getCompleteLeaves().isEmpty());
yield true;
}
case PROVE_CELL_MIGHT_NOT_BE -> {
// One solution differs from the given
Expand All @@ -394,9 +397,7 @@ public boolean isPuzzleComplete() {
if (!cellsMatchBetweenBoards(getOpenLeaves())) {
yield false;
}

// There must be a proven solution
yield (goal.assumeSolution() || !getCompleteLeaves().isEmpty());
yield cellsMatchBetweenBoards(getOpenLeaves());
}
case PROVE_MULTIPLE_CELL_VALUE -> {
// The following line yielding true vs false determines if 0 solutions counts
Expand All @@ -422,15 +423,11 @@ public boolean isPuzzleComplete() {
}

// If there is a solution, it must have this set of values
if (goal.assumeSolution() && !getOpenLeaves().isEmpty()) {
for (TreeNode node : getOpenLeaves()) {
if (countGoalMatches(node, true) != goal.getCells().size()) {
yield false;
}
}
yield true;
for (TreeNode node : getOpenLeaves())
{
if (countGoalMatches(node, true) != goal.getCells().size()) {yield false;}
}
yield false;
yield true;
}
case PROVE_VALUES_ARE_IMPOSSIBLE -> {
// No open branch matches these values
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/edu/rpi/legup/model/PuzzleExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,6 @@ protected void appendGoalElement(Document newDocument, Element boardElement, Gri

Element goalElement = newDocument.createElement("goal");
goalElement.setAttribute("type", String.valueOf(goalType));
goalElement.setAttribute(
"assumeSolution", String.valueOf(puzzle.getGoal().assumeSolution()));

boolean hasGoalCells = false;

Expand All @@ -192,15 +190,15 @@ protected void appendGoalElement(Document newDocument, Element boardElement, Gri
}
}

if (!hasGoalCells && puzzle.getGoal().assumeSolution() && puzzle.getGoal() != null) {
if (!hasGoalCells && puzzle.getGoal() != null) {
for (GridCell goalCell : puzzle.getGoal().getCells()) {
Element cellElement = puzzle.getFactory().exportCell(newDocument, goalCell);
goalElement.appendChild(cellElement);
hasGoalCells = true;
}
}

if (hasGoalCells || !puzzle.getGoal().assumeSolution()) {
if (hasGoalCells) {
boardElement.appendChild(goalElement);
}
}
Expand Down
13 changes: 1 addition & 12 deletions src/main/java/edu/rpi/legup/model/gameboard/ElementFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,7 @@ public Goal importGoal(Node node, Board board) throws InvalidFileFormatException
? GoalType.DEFAULT
: GoalType.valueOf(goalTypeString.toUpperCase());

try {
String assumeSolution = attributeList.getNamedItem("assumeSolution").getNodeValue();
if (!(assumeSolution.equalsIgnoreCase("true")
|| assumeSolution.equalsIgnoreCase("false"))) {
throw new InvalidFileFormatException(
"Field 'assumeSolution' must be null, true, or false.");
}
boolean assume = (assumeSolution.equalsIgnoreCase("true"));
return new Goal(goalType, assume);
} catch (NullPointerException e) {
return new Goal(goalType, false);
}
return new Goal(goalType);

} catch (NumberFormatException e) {
throw new InvalidFileFormatException("Factory: unknown value where integer expected");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@
import edu.rpi.legup.ui.JitterlessScrollPane;
import java.awt.Dimension;
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

Expand All @@ -25,7 +17,6 @@ public class ElementFrame extends JPanel {
private JTabbedPane tabbedPane;
private JComboBox<GoalType> goalTypeComboBox;
private JComboBox<PlaceableElement> goalDataTypecomboBox;
private JCheckBox assumeSolutionCheckBox;
private ButtonGroup buttonGroup;

private EditorElementController controller;
Expand Down Expand Up @@ -105,11 +96,6 @@ private JComponent createGoalConditionsPanel() {
selectorPanel2.add(goalDataTypecomboBox, BorderLayout.CENTER);
topPanel.add(selectorPanel2, BorderLayout.SOUTH);

assumeSolutionCheckBox = new JCheckBox("Assume solution");
assumeSolutionCheckBox.addActionListener(
e -> controller.setAssumeSolution(assumeSolutionCheckBox.isSelected()));
topPanel.add(assumeSolutionCheckBox, BorderLayout.CENTER);

goalPanel.add(topPanel, BorderLayout.NORTH);

return goalPanel;
Expand Down
5 changes: 2 additions & 3 deletions src/test/java/goalConditions/ProveAnySolutionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ public void TestSinglePath() throws InvalidFileFormatException {
Assert.assertTrue(
TestUtilities.verifyBoard("goalConditions/ProveAnySolution/CompleteLine", puzzle));

Assert.assertFalse(
TestUtilities.verifyBoard(
"goalConditions/ProveAnySolution/ContradictoryLine", puzzle));
Assert.assertTrue(TestUtilities.verifyBoard(
"goalConditions/ProveAnySolution/ContradictoryLine", puzzle));

Assert.assertFalse(
TestUtilities.verifyBoard(
Expand Down
Loading
Loading