diff --git a/.github/workflows/publish-javadoc.yml b/.github/workflows/publish-javadoc.yml index 37eac9482..4e1e64608 100644 --- a/.github/workflows/publish-javadoc.yml +++ b/.github/workflows/publish-javadoc.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Publish JavaDoc - uses: MathieuSoysal/Javadoc-publisher.yml@v2.3.0 + uses: MathieuSoysal/Javadoc-publisher.yml@v2.4.0 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} javadoc-branch: javadoc diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index a55e7a179..f23d52492 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,5 @@ - \ No newline at end of file diff --git a/bin/main/edu/rpi/legup/legup/config b/bin/main/edu/rpi/legup/legup/config index 24fdcf365..19e63a2a3 100644 --- a/bin/main/edu/rpi/legup/legup/config +++ b/bin/main/edu/rpi/legup/legup/config @@ -7,7 +7,7 @@ + fileCreationDisabled="false"/> - \ No newline at end of file + diff --git a/bin/main/edu/rpi/legup/log4j2.properties b/bin/main/edu/rpi/legup/log4j2.properties index de1fa02ed..4f2556c2d 100644 --- a/bin/main/edu/rpi/legup/log4j2.properties +++ b/bin/main/edu/rpi/legup/log4j2.properties @@ -1,15 +1,15 @@ -# Logging level -# Root logger option -log4j.rootLogger=DEBUG, stdout, file -# Redirect log messages to console -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -# Redirect log messages to a log file, support file rolling. -log4j.appender.file=org.apache.log4j.RollingFileAppender -log4j.appender.file.File=Legup.log -log4j.appender.file.MaxFileSize=5MB -log4j.appender.file.MaxBackupIndex=10 -log4j.appender.file.layout=org.apache.log4j.PatternLayout +# Logging level +# Root logger option +log4j.rootLogger=DEBUG, stdout, file +# Redirect log messages to console +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n +# Redirect log messages to a log file, support file rolling. +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.File=Legup.log +log4j.appender.file.MaxFileSize=5MB +log4j.appender.file.MaxBackupIndex=10 +log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/build.gradle b/build.gradle index fafa54cac..062a2cbff 100644 --- a/build.gradle +++ b/build.gradle @@ -16,8 +16,7 @@ sourceCompatibility = 11 dependencies { implementation 'org.jetbrains:annotations:20.1.0' implementation 'org.jetbrains:annotations:20.1.0' - implementation 'com.formdev:flatlaf:3.0' - implementation project(':legup-update') + implementation 'com.formdev:flatlaf:3.+' implementation 'com.google.firebase:firebase-admin:6.3.0' implementation 'org.apache.httpcomponents:httpclient:4.5.1' implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' diff --git a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/CannotFillMiddle b/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/CannotFillMiddle deleted file mode 100644 index e69de29bb..000000000 diff --git a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/LightInVerticalPath b/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/LightInVerticalPath deleted file mode 100644 index 70419c40c..000000000 --- a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/LightInVerticalPath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/CannotLightACellContradictionRule/CannotFillCorners b/build/resources/test/puzzles/lightup/rules/CannotLightACellContradictionRule/CannotFillCorners deleted file mode 100644 index 38b52f04d..000000000 --- a/build/resources/test/puzzles/lightup/rules/CannotLightACellContradictionRule/CannotFillCorners +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/CannotLightACellContradictionRule/CannotFillMiddle b/build/resources/test/puzzles/lightup/rules/CannotLightACellContradictionRule/CannotFillMiddle deleted file mode 100644 index 44086f145..000000000 --- a/build/resources/test/puzzles/lightup/rules/CannotLightACellContradictionRule/CannotFillMiddle +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/BlockEnclosed b/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/BlockEnclosed deleted file mode 100644 index a57a2473e..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/BlockEnclosed +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/CompleteBoardBlockEnclosed b/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/CompleteBoardBlockEnclosed deleted file mode 100644 index f48d240f0..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/CompleteBoardBlockEnclosed +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/CornerBlockEnclosed b/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/CornerBlockEnclosed deleted file mode 100644 index 1a9cd60d9..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/CornerBlockEnclosed +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/ManyBlocksEnclosed b/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/ManyBlocksEnclosed deleted file mode 100644 index 32200d831..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooFewBulbsContradictionRule/ManyBlocksEnclosed +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/BlockEnclosed b/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/BlockEnclosed deleted file mode 100644 index c5760aede..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/BlockEnclosed +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/CompleteBoardBlockEnclosed b/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/CompleteBoardBlockEnclosed deleted file mode 100644 index 88fb0a8f1..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/CompleteBoardBlockEnclosed +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/CornerBlockEnclosed b/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/CornerBlockEnclosed deleted file mode 100644 index a9a8dc5a0..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/CornerBlockEnclosed +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/ManyBlocksEnclosed b/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/ManyBlocksEnclosed deleted file mode 100644 index e743862eb..000000000 --- a/build/resources/test/puzzles/lightup/rules/TooManyBulbsContradictionRule/ManyBlocksEnclosed +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/puzzles files/fillapix/10x10 Fillapix Advanced/FillapixAdvanced10x10_1 b/puzzles files/fillapix/10x10 Fillapix Advanced/FillapixAdvanced10x10_1 new file mode 100644 index 000000000..3706caf3b --- /dev/null +++ b/puzzles files/fillapix/10x10 Fillapix Advanced/FillapixAdvanced10x10_1 @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/puzzles files/fillapix/10x10 Fillapix Very Easy/03010000074 b/puzzles files/fillapix/10x10 Fillapix Basic/FillapixBasic10x10_1 similarity index 100% rename from puzzles files/fillapix/10x10 Fillapix Very Easy/03010000074 rename to puzzles files/fillapix/10x10 Fillapix Basic/FillapixBasic10x10_1 diff --git a/puzzles files/fillapix/15x15 Fillapix Advanced/FillapixAdvanced15x15_1 b/puzzles files/fillapix/15x15 Fillapix Advanced/FillapixAdvanced15x15_1 new file mode 100644 index 000000000..954d6d409 --- /dev/null +++ b/puzzles files/fillapix/15x15 Fillapix Advanced/FillapixAdvanced15x15_1 @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/puzzles files/fillapix/15x15 Fillapix Basic/FillapixBasic15x15_1 b/puzzles files/fillapix/15x15 Fillapix Basic/FillapixBasic15x15_1 new file mode 100644 index 000000000..d17e230f0 --- /dev/null +++ b/puzzles files/fillapix/15x15 Fillapix Basic/FillapixBasic15x15_1 @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/puzzles files/fillapix/20x20 Fillaix Advanced/FillapixAdvanced20x20_1 b/puzzles files/fillapix/20x20 Fillaix Advanced/FillapixAdvanced20x20_1 new file mode 100644 index 000000000..3582ba947 --- /dev/null +++ b/puzzles files/fillapix/20x20 Fillaix Advanced/FillapixAdvanced20x20_1 @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/puzzles files/fillapix/20x20 Fillapix Basic/FillapixBasic20x20_1 b/puzzles files/fillapix/20x20 Fillapix Basic/FillapixBasic20x20_1 new file mode 100644 index 000000000..59d8a2114 --- /dev/null +++ b/puzzles files/fillapix/20x20 Fillapix Basic/FillapixBasic20x20_1 @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/puzzles files/fillapix/20x20 Fillapix Basic/FillapixBasic20x20_2 b/puzzles files/fillapix/20x20 Fillapix Basic/FillapixBasic20x20_2 new file mode 100644 index 000000000..af3f936f8 --- /dev/null +++ b/puzzles files/fillapix/20x20 Fillapix Basic/FillapixBasic20x20_2 @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/puzzles files/skyscrapers/1646651 b/puzzles files/skyscrapers/1646651 deleted file mode 100644 index 847d8639c..000000000 --- a/puzzles files/skyscrapers/1646651 +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/puzzles files/skyscrapers/easy1.xml b/puzzles files/skyscrapers/easy1.xml deleted file mode 100644 index 9d3135bff..000000000 --- a/puzzles files/skyscrapers/easy1.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/settings.gradle b/settings.gradle index b14b5f5c0..0fe46c84f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1 @@ rootProject.name = 'LEGUP' -include ':legup' -include ':legup-update' - diff --git a/src/main/java/edu/rpi/legup/controller/TreeController.java b/src/main/java/edu/rpi/legup/controller/TreeController.java index b954edd79..6eae4ac3b 100644 --- a/src/main/java/edu/rpi/legup/controller/TreeController.java +++ b/src/main/java/edu/rpi/legup/controller/TreeController.java @@ -2,6 +2,7 @@ import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.tree.Tree; +import edu.rpi.legup.model.tree.TreeElementType; import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.proofeditorui.treeview.*; @@ -42,7 +43,7 @@ public void mousePressed(MouseEvent e) { /** * Mouse Released event sets the cursor back to the default cursor and reset info for panning - * + * Set board modifiability * @param e MouseEvent object */ @Override diff --git a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java index b42f73c9a..a4c157c77 100644 --- a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java @@ -24,6 +24,8 @@ public class AutoCaseRuleCommand extends PuzzleCommand { private List caseTrans; + private static final int MAX_CASES = 10; + /** * AutoCaseRuleCommand Constructor creates a command for validating a case rule * @@ -60,6 +62,7 @@ public void executeCommand() { board.setModifiable(false); transition.setBoard(board); transition.setRule(caseRule); + transition.setSelection(elementView.getPuzzleElement().copy()); caseTrans.add(transition); TreeNode childNode = (TreeNode) tree.addTreeElement(transition); @@ -112,6 +115,10 @@ public String getErrorString() { return "The selection must produce at least one case"; } + if (caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()).size() > MAX_CASES) { + return "The selection can produce a max of " + MAX_CASES + " cases"; + } + return null; } diff --git a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java index a0f58a571..23f8dce21 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java @@ -66,9 +66,11 @@ public void executeCommand() { if (transition == null) { transition = tree.addNewTransition(treeNode); transition.setRule(newRule); + transition.getBoard().setModifiable(false); tree.addTreeElement(transition); } else { + transition.getBoard().setModifiable(false); tree.addTreeElement(treeNode, transition); } diff --git a/src/main/java/edu/rpi/legup/model/gameboard/GridBoard.java b/src/main/java/edu/rpi/legup/model/gameboard/GridBoard.java index 3e94c57ad..d31e8185a 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/GridBoard.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/GridBoard.java @@ -71,15 +71,40 @@ public void setCell(int x, int y, Element e, MouseEvent m) { if (this instanceof TreeTentBoard && ((y == dimension.height && 0 <= x && x < dimension.width) || (x == dimension.width && 0 <= y && y < dimension.height))) { TreeTentBoard treeTentBoard = ((TreeTentBoard) this); TreeTentClue clue = treeTentBoard.getClue(x, y); - if (y == dimension.height && clue.getData() < dimension.width) { - clue.setData(clue.getData() + 1); + if (y == dimension.height) { + if (m.getButton() == MouseEvent.BUTTON1) { + if (clue.getData() < dimension.height) { + clue.setData(clue.getData() + 1); + } + else { + clue.setData(0); + } + } + else { + if (clue.getData() > 0) { + clue.setData(clue.getData() - 1); + } + else { + clue.setData(dimension.height); + } + } } - else { - if (x == dimension.width && clue.getData() < dimension.height) { - clue.setData(clue.getData() + 1); + else { //x == dimension.width + if (m.getButton() == MouseEvent.BUTTON1) { + if (clue.getData() < dimension.width) { + clue.setData(clue.getData() + 1); + } + else { + clue.setData(0); + } } else { - clue.setData(0); + if (clue.getData() > 0) { + clue.setData(clue.getData() - 1); + } + else { + clue.setData(dimension.width); + } } } } diff --git a/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java b/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java index 97c9205cf..3d84287e3 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java @@ -11,6 +11,7 @@ public abstract class PuzzleElement { protected boolean isModified; protected boolean isGiven; protected boolean isValid; + protected int casesDepended; /** * PuzzleElement Constructor creates a new puzzle element. @@ -22,6 +23,7 @@ public PuzzleElement() { this.isModified = false; this.isGiven = false; this.isValid = true; + this.casesDepended = 0; } /** @@ -148,6 +150,24 @@ public void setValid(boolean isValid) { this.isValid = isValid; } + /** + * Get the number of case rules that depend upon the state of this element + * + * @return number of cases + */ + public int getCasesDepended() { + return this.casesDepended; + } + + /** + * Sets the number of case rules that depend upon the state of this element + * + * @param cases number of cases + */ + public void setCasesDepended(int cases) { + this.casesDepended = cases; + } + /** * Tests whether two puzzle elements objects have the same puzzle element * diff --git a/src/main/java/edu/rpi/legup/model/rules/CaseRule.java b/src/main/java/edu/rpi/legup/model/rules/CaseRule.java index d9c7e73e5..efb96e21a 100644 --- a/src/main/java/edu/rpi/legup/model/rules/CaseRule.java +++ b/src/main/java/edu/rpi/legup/model/rules/CaseRule.java @@ -7,9 +7,8 @@ import edu.rpi.legup.model.tree.TreeTransition; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.Set; import static edu.rpi.legup.model.rules.RuleType.CASE; @@ -79,6 +78,7 @@ public String checkRule(TreeTransition transition) { String check = checkRuleRaw(transition); + // Mark transition and new data as valid or not boolean isCorrect = (check == null); for (TreeTransition childTrans : parentNodes.get(0).getChildren()) { childTrans.setCorrect(isCorrect); @@ -125,6 +125,31 @@ public String checkRuleAt(TreeTransition transition, PuzzleElement puzzleElement */ @Override public abstract String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement); + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = new ArrayList<>(); + + List cases = getCases(board,puzzleElement); + for (Board caseBoard : cases) { + Set data = caseBoard.getModifiedData(); + for (PuzzleElement element : data) { + if(!elements.contains(board.getPuzzleElement(element))){ + elements.add(board.getPuzzleElement(element)); + } + } + } + + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/model/rules/DirectRule.java b/src/main/java/edu/rpi/legup/model/rules/DirectRule.java index 4acc7573e..847764b7b 100644 --- a/src/main/java/edu/rpi/legup/model/rules/DirectRule.java +++ b/src/main/java/edu/rpi/legup/model/rules/DirectRule.java @@ -33,6 +33,10 @@ public String checkRule(TreeTransition transition) { transition.getParents().get(0).getChildren().size() != 1) { return "State must have only 1 parent and 1 child"; } + else if (finalBoard.getModifiedData().isEmpty()) { + // null transition + return null; + } else { return checkRuleRaw(transition); } @@ -48,6 +52,11 @@ public String checkRule(TreeTransition transition) { public String checkRuleRaw(TreeTransition transition) { Board finalBoard = transition.getBoard(); String checkStr = null; + + // Go directly to specific direct rule's judgement if no cell's are edited + if (finalBoard.getModifiedData().size() == 0) { + checkStr = checkRuleRawAt(transition, null); + } for (PuzzleElement puzzleElement : finalBoard.getModifiedData()) { String tempStr = checkRuleAt(transition, puzzleElement); if (tempStr != null) { diff --git a/src/main/java/edu/rpi/legup/model/tree/TreeTransition.java b/src/main/java/edu/rpi/legup/model/tree/TreeTransition.java index e1d042626..72572ac72 100644 --- a/src/main/java/edu/rpi/legup/model/tree/TreeTransition.java +++ b/src/main/java/edu/rpi/legup/model/tree/TreeTransition.java @@ -2,6 +2,7 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.rules.RuleType; @@ -12,6 +13,8 @@ public class TreeTransition extends TreeElement { private ArrayList parents; private TreeNode childNode; private Rule rule; + + private PuzzleElement selection; private boolean isCorrect; private boolean isVerified; @@ -26,6 +29,7 @@ public TreeTransition(Board board) { this.childNode = null; this.board = board; this.rule = null; + this.selection = null; this.isCorrect = false; this.isVerified = false; } @@ -87,13 +91,42 @@ public void propagateChange(PuzzleElement element) { } } else { + // Overwrite previous modifications to this element + board.removeModifiedData(board.getPuzzleElement(element)); + + // apply changes to tranistion + board.notifyChange(element); + + // mark first transition as modified + if (!board.getPuzzleElement(element).equalsData(parents.get(0).getBoard().getPuzzleElement(element))) { + board.addModifiedData(element); + } + + // propagate to children if (childNode != null) { - board.notifyChange(element); - childNode.getBoard().notifyChange(element.copy()); - for (TreeTransition child : childNode.getChildren()) { - PuzzleElement copy = element.copy(); + + // find starting board + TreeNode head = childNode; + while (head.getParent() != null) { + head = head.getParent().getParents().get(0); + } + Board headBoard = head.getBoard(); + + PuzzleElement copy = element.copy(); + // Set as modifiable if reverted to starting value (and started modifiable) + if (headBoard.getPuzzleElement(element).equalsData(element)) { + copy.setModifiable(headBoard.getPuzzleElement(element).isModifiable()); + } + else{ copy.setModifiable(false); - child.propagateChange(copy); + } + + // apply changes to result node + childNode.getBoard().notifyChange(copy); + + // apply to all child transitions + for (TreeTransition child : childNode.getChildren()) { + child.propagateChange(copy.copy()); } } } @@ -327,6 +360,27 @@ public void setRule(Rule rule) { isVerified = false; } + /** + * Gets he selected element associated with this transition + * + * @return If this is a case rule, the selected element for that rule, null otherwise + */ + public PuzzleElement getSelection() { + if (this.rule instanceof CaseRule) { + return selection; + } + return null; + } + + /** + * Sets the selected element associated with this transition + * + * @param selection selected element for this transition + */ + public void setSelection(PuzzleElement selection) { + this.selection = selection; + } + /** * Gets whether this transition is correctly justified * diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java index ca10ab266..ef78f66aa 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/Fillapix.java @@ -26,6 +26,8 @@ public Fillapix() { @Override public void initializeView() { boardView = new FillapixView((FillapixBoard) currentBoard); + boardView.setBoard(currentBoard); + addBoardListener(boardView); } @Override @@ -42,8 +44,7 @@ public Board generatePuzzle(int difficulty) { * @return true if the given dimensions are valid for Fillapix, false otherwise */ public boolean isValidDimensions(int rows, int columns) { - // This is a placeholder, this method needs to be implemented - throw new UnsupportedOperationException(); + return super.isValidDimensions(rows, columns); } @Override diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixBoard.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixBoard.java index 24615db5c..67987a6fd 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixBoard.java @@ -53,6 +53,9 @@ public int getNumCells(FillapixCell cell, FillapixCellType type) { int numCells = 0; for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { + if (loc.x + i > dimension.width || loc.y + j > dimension.height) { + continue; + } FillapixCell c = getCell(loc.x + i, loc.y + j); if (c != null && c.getType() == type) { numCells++; diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCell.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCell.java index 00f66708d..5e6d4b9ed 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCell.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCell.java @@ -1,10 +1,13 @@ package edu.rpi.legup.puzzle.fillapix; +import edu.rpi.legup.model.elements.Element; import edu.rpi.legup.model.gameboard.GridCell; import java.awt.*; +import java.awt.event.MouseEvent; +import java.util.Objects; -public class FillapixCell extends GridCell { +public class FillapixCell extends GridCell implements Comparable { public static final int DEFAULT_VALUE = 10; @@ -33,10 +36,44 @@ public FillapixCellType getType() { } } - public void setType(FillapixCellType type) { + public void setCellType(FillapixCellType type) { data = type.value * 100 + (data % 100); } + @Override + public void setType(Element e, MouseEvent m) { + switch(e.getElementID()) { + case "FPIX-PLAC-0001": + this.setCellType(FillapixCellType.BLACK); + break; + case "FPIX-PLAC-0002": + this.setCellType(FillapixCellType.WHITE); + break; + case "FPIX-UNPL-0001": + int n = this.getNumber(); + switch (m.getButton()) { + case MouseEvent.BUTTON1: + n++; + break; + case MouseEvent.BUTTON3: + n--; + break; + } + if (n > 9) { + n = 0; + } + if (n < 0) { + n = 9; + } + this.setNumber(n); + break; + default: + this.setCellType(FillapixCellType.UNKNOWN); + this.data = -1; + break; + } + } + /** * Performs a deep copy on the FillapixCell * @@ -49,4 +86,19 @@ public FillapixCell copy() { cell.setModifiable(isModifiable); return cell; } + + public boolean equals(FillapixCell otherCell) { +// return this.location.equals(otherCell.location) && this.index == otherCell.index && this.data == otherCell.data; + //return this.index == otherCell.index && this.data == otherCell.data; + //return this.index == otherCell.index; + return this.location.x == otherCell.location.x && this.location.y == otherCell.location.y; + } + + public int compareTo(FillapixCell otherCell) { + return this.index - otherCell.index; + } + + public int hashCode() { + return Objects.hash(this.index); + } } \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCellController.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCellController.java index 62d14630d..df3bba403 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCellController.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixCellController.java @@ -15,15 +15,32 @@ public void changeCell(MouseEvent e, PuzzleElement puzzleElement) { } else { if (cell.getType() == FillapixCellType.UNKNOWN) { - cell.setType(FillapixCellType.BLACK); + cell.setCellType(FillapixCellType.BLACK); } else { if (cell.getType() == FillapixCellType.BLACK) { - cell.setType(FillapixCellType.WHITE); + cell.setCellType(FillapixCellType.WHITE); } else { if (cell.getType() == FillapixCellType.WHITE) { - cell.setType(FillapixCellType.UNKNOWN); + cell.setCellType(FillapixCellType.UNKNOWN); + } + } + } + } + } + else { + if (e.getButton() == MouseEvent.BUTTON3) { + if (cell.getType() == FillapixCellType.UNKNOWN) { + cell.setCellType(FillapixCellType.WHITE); + } + else { + if (cell.getType() == FillapixCellType.BLACK) { + cell.setCellType(FillapixCellType.UNKNOWN); + } + else { + if (cell.getType() == FillapixCellType.WHITE) { + cell.setCellType(FillapixCellType.BLACK); } } } diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixElementView.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixElementView.java index 00d0a6807..93fa0d451 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixElementView.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixElementView.java @@ -47,7 +47,7 @@ public void drawElement(Graphics2D graphics2D) { break; } graphics2D.fillRect(location.x, location.y, size.width, size.height); - if (cell.getNumber() != -1) { + if (cell.getNumber() >= 0 && cell.getNumber() < 10) { graphics2D.setColor(type == FillapixCellType.WHITE ? BLACK_COLOR : WHITE_COLOR); graphics2D.setFont(FONT); FontMetrics metrics = graphics2D.getFontMetrics(FONT); diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java index 6c30b2272..5213e7139 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java @@ -32,7 +32,18 @@ public boolean acceptsTextInput() { */ @Override public void initializeBoard(int rows, int columns) { + FillapixBoard fillapixBoard = new FillapixBoard(columns, rows); + for (int y = 0; y < rows; y++) { + for (int x = 0; x < columns; x++) { + FillapixCell cell = new FillapixCell(FillapixCellType.UNKNOWN.value, new Point(x, y)); + cell.setIndex(y * columns + x); + cell.setNumber(FillapixCell.DEFAULT_VALUE); + cell.setModifiable(true); + fillapixBoard.setCell(x, y, cell); + } + } + puzzle.setCurrentBoard(fillapixBoard); } /** diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixUtilities.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixUtilities.java index 2098676b5..a7feac91d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixUtilities.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixUtilities.java @@ -1,23 +1,206 @@ package edu.rpi.legup.puzzle.fillapix; +import edu.rpi.legup.model.rules.ContradictionRule; import edu.rpi.legup.puzzle.fillapix.rules.TooFewBlackCellsContradictionRule; import edu.rpi.legup.puzzle.fillapix.rules.TooManyBlackCellsContradictionRule; +import java.awt.*; +import java.util.ArrayList; + public class FillapixUtilities { public static boolean isForcedBlack(FillapixBoard board, FillapixCell cell) { TooFewBlackCellsContradictionRule tooManyBlackCells = new TooFewBlackCellsContradictionRule(); FillapixBoard whiteCaseBoard = board.copy(); FillapixCell whiteCell = (FillapixCell) whiteCaseBoard.getPuzzleElement(cell); - whiteCell.setType(FillapixCellType.WHITE); - return tooManyBlackCells.checkContradictionAt(whiteCaseBoard, cell) != null; + whiteCell.setCellType(FillapixCellType.WHITE); + ArrayList adjCells = getAdjacentCells(whiteCaseBoard, whiteCell); + for (FillapixCell adjCell : adjCells) { + if (tooManyBlackCells.checkContradictionAt(whiteCaseBoard, adjCell) == null) { + return true; + } + } + return false; } public static boolean isForcedWhite(FillapixBoard board, FillapixCell cell) { TooManyBlackCellsContradictionRule tooManyBlackCells = new TooManyBlackCellsContradictionRule(); FillapixBoard blackCaseBoard = board.copy(); FillapixCell blackCell = (FillapixCell) blackCaseBoard.getPuzzleElement(cell); - blackCell.setType(FillapixCellType.BLACK); - return tooManyBlackCells.checkContradictionAt(blackCaseBoard, cell) != null; + blackCell.setCellType(FillapixCellType.BLACK); + ArrayList adjCells = getAdjacentCells(blackCaseBoard, blackCell); + for (FillapixCell adjCell : adjCells) { + if (tooManyBlackCells.checkContradictionAt(blackCaseBoard, adjCell) == null) { + return true; + } + } + return false; + } + + public static boolean isComplete(FillapixBoard board, FillapixCell cell) { + int cellNum = cell.getNumber(); + int cellTouchBlack = 0; + ArrayList adjCells = getAdjacentCells(board, cell); + for (FillapixCell adjCell : adjCells) { + if (adjCell.getType() == FillapixCellType.BLACK) { + cellTouchBlack++; + } + } + return cellNum == cellTouchBlack; + } + + public static boolean hasEmptyAdjacent(FillapixBoard board, FillapixCell cell) { + ArrayList adjCells = getAdjacentCells(board, cell); + for (FillapixCell adjCell : adjCells) { + if (adjCell.getType() == FillapixCellType.UNKNOWN) { + return true; + } + } + return false; + } + + /** + * Gets all cells adjacent to a specific cell. The cell itself will be included. + */ + public static ArrayList getAdjacentCells(FillapixBoard board, FillapixCell cell) { + ArrayList adjCells = new ArrayList(); + Point cellLoc = cell.getLocation(); + for (int i=-1; i <= 1; i++) { + for (int j=-1; j <= 1; j++) { + if (cellLoc.getX() + i < 0 || cellLoc.y + j < 0 || cellLoc.x + i >= board.getWidth() || cellLoc.y + j >= board.getHeight()) { + continue; + } + FillapixCell adjCell = board.getCell(cellLoc.x + i, cellLoc.y + j); + if (adjCell == null) { + continue; + } + adjCells.add(adjCell); + } + } + return adjCells; + } + + /** + * Gets all cells that are contained in the square defined as having 'distance' + * cells between the center and the outer wall. For example, distance = 1:

+ * |X|X|X|X|X|

+ * |X| | | |X|

+ * |X| |O| |X|

+ * |X| | | |X|

+ * |X|X|X|X|X|

+ * O is 'cell', and all 'X' will be returned in the ArrayList + */ + public static ArrayList getCellsAtDistance(FillapixBoard board, FillapixCell cell, int distance) { + ArrayList adjCells = new ArrayList(); + Point cellLoc = cell.getLocation(); + int i = 0, j = 0; + // top line + for (i = cellLoc.x - (distance), j = cellLoc.y - (distance+1); i <= cellLoc.x + (distance+1); i++) { + if (cellLoc.getX() + i < 0 || cellLoc.y + j < 0 || cellLoc.x + i >= board.getWidth() || cellLoc.y + j >= board.getHeight()) { + continue; + } + FillapixCell adjCell = board.getCell(cellLoc.x + i, cellLoc.y + j); + if (adjCell == null) { + continue; + } + adjCells.add(adjCell); + } + // right line + for (i = cellLoc.x + (distance+1), j = cellLoc.y - (distance); j <= cellLoc.y + (distance+1); j++) { + if (cellLoc.getX() + i < 0 || cellLoc.y + j < 0 || cellLoc.x + i >= board.getWidth() || cellLoc.y + j >= board.getHeight()) { + continue; + } + FillapixCell adjCell = board.getCell(cellLoc.x + i, cellLoc.y + j); + if (adjCell == null) { + continue; + } + adjCells.add(adjCell); + } + // bottom line + for (i = cellLoc.x + (distance), j = cellLoc.y + (distance+1); i <= cellLoc.x - (distance+1); i--) { + if (cellLoc.getX() + i < 0 || cellLoc.y + j < 0 || cellLoc.x + i >= board.getWidth() || cellLoc.y + j >= board.getHeight()) { + continue; + } + FillapixCell adjCell = board.getCell(cellLoc.x + i, cellLoc.y + j); + if (adjCell == null) { + continue; + } + adjCells.add(adjCell); + } + // left line + for (i = cellLoc.x - (distance+1), j = cellLoc.y + (distance); j <= cellLoc.y - (distance+1); j--) { + if (cellLoc.getX() + i < 0 || cellLoc.y + j < 0 || cellLoc.x + i >= board.getWidth() || cellLoc.y + j >= board.getHeight()) { + continue; + } + FillapixCell adjCell = board.getCell(cellLoc.x + i, cellLoc.y + j); + if (adjCell == null) { + continue; + } + adjCells.add(adjCell); + } + + return adjCells; + } + + /** + * Finds all possible combinations of chosenNumObj items can be + * chosen from totalNumObj total items. + * For example, if 1 item is chosen from 2 possible items, the combinations + * are: + *

[ [true,false], [false,true] ]
+ * + * @param totalNumItems the total number of items that can possibly be chosen + * @param chosenNumItems the number of items to be chosen + * + * @return an ArrayList of Boolean arrays. Each index in the ArrayList represents + * a distinct combination. Each Boolean array will be totalNumItems + * long and each index will be true if the corresponding item is + * included in that combination, and false otherwise. + */ + public static ArrayList getCombinations(int chosenNumItems, int totalNumItems) { + ArrayList combinations = new ArrayList(); + + // calculate all combinations + boolean[] array = new boolean[totalNumItems]; + recurseCombinations(combinations, 0, chosenNumItems, 0, totalNumItems, array); + + return combinations; + } + + private static void recurseCombinations(ArrayList result, int curIndex, int maxBlack, int numBlack, int len, boolean[] workingArray) { + if (curIndex == len) { + // complete, but not valid solution + if (numBlack != maxBlack) { + return; + } + // complete and valid solution + result.add(workingArray.clone()); + return; + } + // there is no chance of completing the required number of solutions, so quit + if (len - curIndex < maxBlack - numBlack) { + return; + } + + if (numBlack < maxBlack) { + workingArray[curIndex] = true; + recurseCombinations(result, curIndex+1, maxBlack, numBlack+1, len, workingArray); + } + workingArray[curIndex] = false; + recurseCombinations(result, curIndex+1, maxBlack, numBlack, len, workingArray); + } + + public static boolean checkBoardForContradiction(FillapixBoard board) { + ContradictionRule tooManyBlack = new TooManyBlackCellsContradictionRule(); + ContradictionRule tooManyWhite = new TooFewBlackCellsContradictionRule(); + for (int i= 0; i < board.getWidth(); i++) { + for (int j=0; j < board.getHeight(); j++) { + if (tooManyBlack.checkContradictionAt(board, board.getCell(i, j)) == null || + tooManyWhite.checkContradictionAt(board, board.getCell(i, j)) == null) { + return true; + } + } + } + return false; } } diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/BlackTile.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/BlackTile.java new file mode 100644 index 000000000..7e43fc6b4 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/BlackTile.java @@ -0,0 +1,9 @@ +package edu.rpi.legup.puzzle.fillapix.elements; + +import edu.rpi.legup.model.elements.PlaceableElement; + +public class BlackTile extends PlaceableElement { + public BlackTile() { + super("FPIX-PLAC-0001", "Black Tile", "The black tile", "edu/rpi/legup/images/fillapix/tiles/BlackTile.png"); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/NumberTile.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/NumberTile.java new file mode 100644 index 000000000..beee70e21 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/NumberTile.java @@ -0,0 +1,27 @@ +package edu.rpi.legup.puzzle.fillapix.elements; + +import edu.rpi.legup.model.elements.NonPlaceableElement; + +public class NumberTile extends NonPlaceableElement { + private int object_num; + + public NumberTile() { + super("FPIX-UNPL-0001", "Number Tile", "A numbered tile", "edu/rpi/legup/images/fillapix/tiles/NumberTile.png"); + object_num = 0; + } + + /** + * @return this object's tile number... + */ + public int getTileNumber() { + return object_num; + } + + /** + * @param num Amount to set tile object to. + */ + public void setTileNumber(int num) { + object_num = num; + } + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/UnknownTile.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/UnknownTile.java new file mode 100644 index 000000000..ef754782f --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/UnknownTile.java @@ -0,0 +1,9 @@ +package edu.rpi.legup.puzzle.fillapix.elements; + +import edu.rpi.legup.model.elements.NonPlaceableElement; + +public class UnknownTile extends NonPlaceableElement { + public UnknownTile() { + super("FPIX-UNPL-0002", "Unknown Tile", "A blank tile", "edu/rpi/legup/images/fillapix/tiles/UnknownTile.png"); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/WhiteTile.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/WhiteTile.java new file mode 100644 index 000000000..dd27d2834 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/WhiteTile.java @@ -0,0 +1,9 @@ +package edu.rpi.legup.puzzle.fillapix.elements; + +import edu.rpi.legup.model.elements.PlaceableElement; + +public class WhiteTile extends PlaceableElement { + public WhiteTile() { + super("FPIX-PLAC-0002", "White Tile", "The white tile", "edu/rpi/legup/images/fillapix/tiles/WhiteTile.png"); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/fillapix_elements_reference_sheet.txt b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/fillapix_elements_reference_sheet.txt new file mode 100644 index 000000000..0409fa800 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/elements/fillapix_elements_reference_sheet.txt @@ -0,0 +1,5 @@ +FPIX-PLAC-0001 : BlackTile +FPIX-PLAC-0002 : WhiteTile + +FPIX-UNPL-0001 : NumberTile +FPIX-UNPL-0002 : UnknownTile \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java index fd6b7c022..1e5151c48 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java @@ -40,13 +40,13 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { Board case1 = board.copy(); FillapixCell cell1 = (FillapixCell) case1.getPuzzleElement(puzzleElement); - cell1.setType(FillapixCellType.BLACK); + cell1.setCellType(FillapixCellType.BLACK); case1.addModifiedData(cell1); cases.add(case1); Board case2 = board.copy(); FillapixCell cell2 = (FillapixCell) case2.getPuzzleElement(puzzleElement); - cell2.setType(FillapixCellType.WHITE); + cell2.setCellType(FillapixCellType.WHITE); case2.addModifiedData(cell2); cases.add(case2); diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithBlackDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithBlackDirectRule.java index afd226693..06a8045ed 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithBlackDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithBlackDirectRule.java @@ -8,6 +8,7 @@ import edu.rpi.legup.puzzle.fillapix.FillapixBoard; import edu.rpi.legup.puzzle.fillapix.FillapixCell; import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; public class FinishWithBlackDirectRule extends DirectRule { public FinishWithBlackDirectRule() { @@ -28,7 +29,7 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem return super.getInvalidUseOfRuleMessage() + ": This cell must be black to be applicable with this rule."; } - if (isForcedBlack(parentBoard, cell)) { + if (FillapixUtilities.isForcedBlack(parentBoard, cell)) { return null; } else { @@ -36,14 +37,6 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } } - private boolean isForcedBlack(FillapixBoard board, FillapixCell cell) { - TooFewBlackCellsContradictionRule tooManyBlackCells = new TooFewBlackCellsContradictionRule(); - FillapixBoard whiteCaseBoard = board.copy(); - FillapixCell whiteCell = (FillapixCell) whiteCaseBoard.getPuzzleElement(cell); - whiteCell.setType(FillapixCellType.WHITE); - return tooManyBlackCells.checkContradictionAt(whiteCaseBoard, cell) == null; - } - /** * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. * @@ -55,8 +48,8 @@ public Board getDefaultBoard(TreeNode node) { FillapixBoard fillapixBoard = (FillapixBoard) node.getBoard().copy(); for (PuzzleElement element : fillapixBoard.getPuzzleElements()) { FillapixCell cell = (FillapixCell) element; - if (cell.getType() == FillapixCellType.UNKNOWN && isForcedBlack((FillapixBoard) node.getBoard(), cell)) { - cell.setType(FillapixCellType.BLACK); + if (cell.getType() == FillapixCellType.UNKNOWN && FillapixUtilities.isForcedBlack((FillapixBoard) node.getBoard(), cell)) { + cell.setCellType(FillapixCellType.BLACK); fillapixBoard.addModifiedData(cell); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithWhiteDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithWhiteDirectRule.java index ec482d5f7..7e213a59c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithWhiteDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/FinishWithWhiteDirectRule.java @@ -8,10 +8,11 @@ import edu.rpi.legup.puzzle.fillapix.FillapixBoard; import edu.rpi.legup.puzzle.fillapix.FillapixCell; import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; public class FinishWithWhiteDirectRule extends DirectRule { public FinishWithWhiteDirectRule() { - super("FFIX-BASC-0002", + super("FPIX-BASC-0002", "Finish with White", "The remaining unknowns around and on a cell must be white to satisfy the number", "edu/rpi/legup/images/fillapix/rules/FinishWithWhite.png"); @@ -28,7 +29,7 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem return super.getInvalidUseOfRuleMessage() + ": This cell must be white to be applicable with this rule"; } - if (isForcedWhite(parentBoard, cell)) { + if (FillapixUtilities.isForcedWhite(parentBoard, cell)) { return null; } else { @@ -36,14 +37,6 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } } - private boolean isForcedWhite(FillapixBoard board, FillapixCell cell) { - TooManyBlackCellsContradictionRule tooManyBlackCells = new TooManyBlackCellsContradictionRule(); - FillapixBoard blackCaseBoard = board.copy(); - FillapixCell blackCell = (FillapixCell) blackCaseBoard.getPuzzleElement(cell); - blackCell.setType(FillapixCellType.BLACK); - return tooManyBlackCells.checkContradictionAt(blackCaseBoard, cell) == null; - } - /** * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. * @@ -55,8 +48,8 @@ public Board getDefaultBoard(TreeNode node) { FillapixBoard fillapixBoard = (FillapixBoard) node.getBoard().copy(); for (PuzzleElement element : fillapixBoard.getPuzzleElements()) { FillapixCell cell = (FillapixCell) element; - if (cell.getType() == FillapixCellType.UNKNOWN && isForcedWhite((FillapixBoard) node.getBoard(), cell)) { - cell.setType(FillapixCellType.WHITE); + if (cell.getType() == FillapixCellType.UNKNOWN && FillapixUtilities.isForcedWhite((FillapixBoard) node.getBoard(), cell)) { + cell.setCellType(FillapixCellType.WHITE); fillapixBoard.addModifiedData(cell); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/MirrorDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/MirrorDirectRule.java new file mode 100644 index 000000000..656cedb3f --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/MirrorDirectRule.java @@ -0,0 +1,103 @@ +package edu.rpi.legup.puzzle.fillapix.rules; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.rules.DirectRule; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.fillapix.FillapixBoard; +import edu.rpi.legup.puzzle.fillapix.FillapixCell; +import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; + +public class MirrorDirectRule extends DirectRule { + public MirrorDirectRule() { + super("FPIX-BASC-0003", + "Mirror", + "Two adjacent clues with the same value must have the same number of black squares in their unshared regions", + "edu/rpi/legup/images/fillapix/rules/Mirror.png"); + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + FillapixBoard board = (FillapixBoard) transition.getBoard(); + FillapixBoard parentBoard = (FillapixBoard) transition.getParents().get(0).getBoard().copy(); + FillapixCell cell = (FillapixCell) board.getPuzzleElement(puzzleElement); + FillapixCell parentCell = (FillapixCell) parentBoard.getPuzzleElement(puzzleElement); + + // cell has to have been empty before + if (parentCell.getType() != FillapixCellType.UNKNOWN) { + return super.getInvalidUseOfRuleMessage(); + } + + // parentBoard cannot have any contradictions + if (FillapixUtilities.checkBoardForContradiction(parentBoard)) { + return super.getInvalidUseOfRuleMessage(); + } + + // find all cells adjacent to cell that are numbered + ArrayList adjCells = FillapixUtilities.getAdjacentCells(parentBoard, parentCell); + ArrayList adjNums = new ArrayList(); + for (int i=0; i < adjCells.size(); i++) { + if ((adjCells.get(i)).getNumber() >= 0 && adjCells.get(i).getNumber() < 10) { + adjNums.add(adjCells.get(i)); + } + } + // the numbered cells must be next to another numbered cell of the same value + Iterator itr = adjNums.iterator(); + while (itr.hasNext()) { + FillapixCell adjNum = itr.next(); + adjCells = FillapixUtilities.getAdjacentCells(parentBoard, adjNum); + boolean found = false; + for (FillapixCell adjCell : adjCells) { + if (adjCell.getNumber() == adjNum.getNumber() && adjCell.getIndex() != adjNum.getIndex()) { + found = true; + } + } + if (!found) { + itr.remove(); + } + } + + // change the color of the parentCell, and check if there exists a valid board + if (cell.getType() == FillapixCellType.BLACK) { + parentCell.setCellType(FillapixCellType.WHITE); + } + else { + parentCell.setCellType(FillapixCellType.BLACK); + } + parentBoard.addModifiedData(parentCell); + CaseRule completeClue = new SatisfyClueCaseRule(); + List caseBoards; + for (FillapixCell adjNum : adjNums) { + caseBoards = completeClue.getCases(parentBoard, adjNum); + boolean found = true; + for (Board b : caseBoards) { + if (!FillapixUtilities.checkBoardForContradiction((FillapixBoard) b)) { + found = false; + } + } + if (found) { + return null; + } + } + + return super.getInvalidUseOfRuleMessage(); + } + + /** + * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * + * @param node tree node used to create default transition board + * @return default board or null if this rule cannot be applied to this tree node + */ + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/NonTouchingSharedDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/NonTouchingSharedDirectRule.java new file mode 100644 index 000000000..fe94dbcb4 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/NonTouchingSharedDirectRule.java @@ -0,0 +1,99 @@ +package edu.rpi.legup.puzzle.fillapix.rules; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.rules.DirectRule; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.fillapix.FillapixBoard; +import edu.rpi.legup.puzzle.fillapix.FillapixCell; +import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; + +public class NonTouchingSharedDirectRule extends DirectRule { + public NonTouchingSharedDirectRule() { + super("FPIX-BASC-0005", + "NonTouching Shared", + "Clues with shared cells have the same difference in black cells in their unshared regions as the difference in their numbers", + "edu/rpi/legup/images/fillapix/rules/TouchingSides.png"); + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + FillapixBoard board = (FillapixBoard) transition.getBoard(); + FillapixBoard parentBoard = (FillapixBoard) transition.getParents().get(0).getBoard().copy(); + FillapixCell cell = (FillapixCell) board.getPuzzleElement(puzzleElement); + FillapixCell parentCell = (FillapixCell) parentBoard.getPuzzleElement(puzzleElement); + + // cell has to have been empty before + if (parentCell.getType() != FillapixCellType.UNKNOWN) { + return super.getInvalidUseOfRuleMessage(); + } + + // parentBoard cannot have any contradictions + if (FillapixUtilities.checkBoardForContradiction(parentBoard)) { + return super.getInvalidUseOfRuleMessage(); + } + + // get all adjCells that have a number + ArrayList adjCells = FillapixUtilities.getAdjacentCells(parentBoard, parentCell); + adjCells.removeIf(x -> x.getNumber() < 0 || x.getNumber() >= 10); + /* remove any number cell that does not have another number cell not + * touching, but sharing cells */ + Iterator itr = adjCells.iterator(); + while (itr.hasNext()) { + ArrayList sharingCells = FillapixUtilities.getCellsAtDistance(parentBoard, parentCell, 1); + boolean found = false; + for (FillapixCell sharingCell : sharingCells) { + if (sharingCell.getNumber() >= 0 && sharingCell.getNumber() < 10) { + found = true; + } + } + if (!found) { + itr.remove(); + } + } + + // change the cell to the opposite color + if (cell.getType() == FillapixCellType.BLACK) { + parentCell.setCellType(FillapixCellType.WHITE); + } + else { + parentCell.setCellType(FillapixCellType.BLACK); + } + // check for some contradiction in all cases + parentBoard.addModifiedData(parentCell); + CaseRule completeClue = new SatisfyClueCaseRule(); + List caseBoards; + for (FillapixCell adjCell : adjCells) { + caseBoards = completeClue.getCases(parentBoard, adjCell); + boolean found = true; + for (Board b : caseBoards) { + if (!FillapixUtilities.checkBoardForContradiction((FillapixBoard) b)) { + found = false; + } + } + if (found) { + return null; + } + } + + return super.getInvalidUseOfRuleMessage(); + } + + /** + * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * + * @param node tree node used to create default transition board + * @return default board or null if this rule cannot be applied to this tree node + */ + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java new file mode 100644 index 000000000..4520add31 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java @@ -0,0 +1,234 @@ +package edu.rpi.legup.puzzle.fillapix.rules; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.CaseBoard; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.fillapix.FillapixBoard; +import edu.rpi.legup.puzzle.fillapix.FillapixCell; +import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; + +public class SatisfyClueCaseRule extends CaseRule { + public SatisfyClueCaseRule() { + super("FPIX-CASE-0002", + "Satisfy Clue", + "Each clue must touch that number of squares.", + "edu/rpi/legup/images/fillapix/cases/SatisfyClue.png"); + } + + @Override + public CaseBoard getCaseBoard(Board board) { + FillapixBoard fillapixBoard = (FillapixBoard) board.copy(); + CaseBoard caseBoard = new CaseBoard(fillapixBoard, this); + fillapixBoard.setModifiable(false); + for (PuzzleElement data : fillapixBoard.getPuzzleElements()) { + FillapixCell cell = (FillapixCell) data; + if (cell.getNumber() >= 0 && cell.getNumber() <= 9 && FillapixUtilities.hasEmptyAdjacent(fillapixBoard, cell)) { + caseBoard.addPickableElement(data); + } + } + return caseBoard; + } + + @Override + public ArrayList getCases(Board board, PuzzleElement puzzleElement) { + ArrayList cases = new ArrayList(); + + // get value of cell + FillapixBoard fillapixBoard = (FillapixBoard) board.copy(); + FillapixCell cell = (FillapixCell) fillapixBoard.getPuzzleElement(puzzleElement); + int cellMaxBlack = cell.getNumber(); + if (cellMaxBlack < 0 || cellMaxBlack > 9) { // cell is not valid cell + return null; + } + + // find number of black & empty squares + int cellNumBlack = 0; + int cellNumEmpty = 0; + ArrayList emptyCells = new ArrayList(); + ArrayList adjCells = FillapixUtilities.getAdjacentCells(fillapixBoard, cell); + for (FillapixCell adjCell : adjCells) { + if (adjCell.getType() == FillapixCellType.BLACK) { + cellNumBlack++; + } + if (adjCell.getType() == FillapixCellType.UNKNOWN) { + cellNumEmpty++; + emptyCells.add(adjCell); + } + } + // no cases if no empty or if too many black already + if (cellNumBlack > cellMaxBlack || cellNumEmpty == 0) { + return cases; + } + + // generate all cases as boolean expressions + ArrayList combinations; + combinations = FillapixUtilities.getCombinations(cellMaxBlack - cellNumBlack, cellNumEmpty); + + for (int i=0; i < combinations.size(); i++) { + Board case_ = board.copy(); + for (int j=0; j < combinations.get(i).length; j++) { + cell = (FillapixCell) case_.getPuzzleElement(emptyCells.get(j)); + if (combinations.get(i)[j]) { + cell.setCellType(FillapixCellType.BLACK); + } + else { + cell.setCellType(FillapixCellType.WHITE); + } + case_.addModifiedData(cell); + } + cases.add(case_); + } + + return cases; + } + + @Override + public String checkRuleRaw(TreeTransition transition) { + TreeNode parent = transition.getParents().get(0); + List childTransitions = parent.getChildren(); + + /* + * In order for the transition to be valid, it can only be applied to + * one cell, thus: + * * there must be modified cells + * * all modified cells must share at least one common adjacent + * cell + * * all modified cells must fit within a 3X3 square + * * the center of one of the possible squaress must be a cell + * with a number + * * that cells possible combinations must match the transitions + * If all the above is verified, then the transition is valid + */ + + + /* ensure there are modified cells */ + Set modCells = transition.getBoard().getModifiedData(); + if (modCells.size() <= 0) { + return super.getInvalidUseOfRuleMessage(); + } + + + /* ensure modified cells occur within a 3X3 square */ + int minVertLoc = Integer.MAX_VALUE, maxVertLoc = Integer.MIN_VALUE; + int minHorzLoc = Integer.MAX_VALUE, maxHorzLoc = Integer.MIN_VALUE; + for (PuzzleElement modCell : modCells) { + Point loc = ((FillapixCell) modCell).getLocation(); + if (loc.x < minHorzLoc) { + minHorzLoc = loc.x; + } + if (loc.x > maxHorzLoc) { + maxHorzLoc = loc.x; + } + if (loc.y < minVertLoc) { + minVertLoc = loc.y; + } + if (loc.y > maxVertLoc) { + maxVertLoc = loc.y; + } + } + if (maxVertLoc - minVertLoc > 3 || maxHorzLoc - minHorzLoc > 3) { + return super.getInvalidUseOfRuleMessage(); + } + + + /* get the center of all possible 3X3 squares, + * and collect all that have numbers */ + FillapixBoard board = (FillapixBoard) transition.getParents().get(0).getBoard(); + Set possibleCenters = new TreeSet(); + possibleCenters.addAll(FillapixUtilities.getAdjacentCells(board, (FillapixCell) modCells.iterator().next())); + for (PuzzleElement modCell : modCells) { + possibleCenters.retainAll((FillapixUtilities.getAdjacentCells(board, (FillapixCell) modCell))); + } + // removing all elements without a valid number + possibleCenters.removeIf(x -> x.getNumber() < 0 || x.getNumber() >= 10); + if (possibleCenters.isEmpty()) { + return super.getInvalidUseOfRuleMessage(); + } + + + /* Now go through the remaining centers, and check if their combinations + * match the transitions */ + for (FillapixCell possibleCenter : possibleCenters) { + int numBlack = 0; + int numEmpty = 0; + int maxBlack = possibleCenter.getNumber(); + for (FillapixCell adjCell : FillapixUtilities.getAdjacentCells(board, possibleCenter)) { + if (adjCell.getType() == FillapixCellType.BLACK) { + numBlack++; + } + if (adjCell.getType() == FillapixCellType.UNKNOWN) { + numEmpty++; + } + } + if (numEmpty <= 0 || numBlack > maxBlack) { + // this cell has no cases (no empty) or is already broken (too many black) + continue; + } + + ArrayList combinations = FillapixUtilities.getCombinations(maxBlack - numBlack, numEmpty); + if (combinations.size() != childTransitions.size()) { + // not this center because combinations do not match transitions + continue; + } + boolean quitEarly = false; + for (TreeTransition trans : childTransitions) { + /* convert the transition board into boolean format, so that it + * can be compared to the combinations */ + FillapixBoard transBoard = (FillapixBoard) trans.getBoard(); + ArrayList transModCells = new ArrayList(); + for (PuzzleElement modCell : modCells) { + transModCells.add((FillapixCell) transBoard.getPuzzleElement(modCell)); + } + + boolean[] translatedModCells = new boolean[transModCells.size()]; + for (int i=0; i < transModCells.size(); i++) { + if (transModCells.get(i).getType() == FillapixCellType.BLACK) { + translatedModCells[i] = true; + } + else { + translatedModCells[i] = false; + } + } + + // try to find the above state in the combinations, remove if found + boolean removed = false; + for (boolean[] combination : combinations) { + if (Arrays.equals(combination, translatedModCells)) { + combinations.remove(combination); + removed = true; + break; + } + } + // if combination not found, no need to check further, just quit + if (!removed) { + quitEarly = true; + break; + } + } + + /* we found a center that is valid */ + if (combinations.isEmpty() && !quitEarly) { + return null; + } + } + + return super.getInvalidUseOfRuleMessage(); + } + + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooFewBlackCellsContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooFewBlackCellsContradictionRule.java index e8dd32860..c37050978 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooFewBlackCellsContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooFewBlackCellsContradictionRule.java @@ -6,8 +6,9 @@ import edu.rpi.legup.puzzle.fillapix.FillapixBoard; import edu.rpi.legup.puzzle.fillapix.FillapixCell; import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; -import java.awt.*; +import java.util.ArrayList; public class TooFewBlackCellsContradictionRule extends ContradictionRule { @@ -31,22 +32,24 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { FillapixBoard fillapixBoard = (FillapixBoard) board; FillapixCell cell = (FillapixCell) fillapixBoard.getPuzzleElement(puzzleElement); - Point loc = cell.getLocation(); - for (int i = -1; i < 2; i++) { - for (int j = -1; j < 2; j++) { - FillapixCell adjCell = fillapixBoard.getCell(loc.x + i, loc.y + j); - if (adjCell != null) { - int cellNum = adjCell.getNumber(); - if (cellNum >= 0) { - int numBlackCells = fillapixBoard.getNumCells(adjCell, FillapixCellType.BLACK); - int numUnknownCells = fillapixBoard.getNumCells(adjCell, FillapixCellType.UNKNOWN); - if (numBlackCells + numUnknownCells < cellNum) { - return null; - } - } - } + int cellNum = cell.getNumber(); + if (cellNum < 0 || cellNum >= 10) { + return super.getNoContradictionMessage(); + } + int numBlack = 0, numEmpty = 0; + ArrayList adjCells = FillapixUtilities.getAdjacentCells(fillapixBoard, cell); + for (FillapixCell adjCell : adjCells) { + if (adjCell.getType() == FillapixCellType.BLACK) { + numBlack++; + } + if (adjCell.getType() == FillapixCellType.UNKNOWN) { + numEmpty++; } } + if (numBlack + numEmpty < cellNum) { + return null; + } + return super.getNoContradictionMessage(); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooManyBlackCellsContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooManyBlackCellsContradictionRule.java index 5a1192cc9..68395ce7f 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooManyBlackCellsContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TooManyBlackCellsContradictionRule.java @@ -6,8 +6,9 @@ import edu.rpi.legup.puzzle.fillapix.FillapixBoard; import edu.rpi.legup.puzzle.fillapix.FillapixCell; import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; -import java.awt.*; +import java.util.ArrayList; public class TooManyBlackCellsContradictionRule extends ContradictionRule { @@ -31,21 +32,21 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { FillapixBoard fillapixBoard = (FillapixBoard) board; FillapixCell cell = (FillapixCell) fillapixBoard.getPuzzleElement(puzzleElement); - Point loc = cell.getLocation(); - for (int i = -1; i < 2; i++) { - for (int j = -1; j < 2; j++) { - FillapixCell adjCell = fillapixBoard.getCell(loc.x + i, loc.y + j); - if (adjCell != null) { - int cellNum = adjCell.getNumber(); - if (cellNum >= 0) { - int numBlackCells = fillapixBoard.getNumCells(adjCell, FillapixCellType.BLACK); - if (numBlackCells > cellNum) { - return null; - } - } - } + int cellNum = cell.getNumber(); + if (cellNum < 0 || cellNum >= 10) { + return super.getNoContradictionMessage(); + } + int numBlack = 0; + ArrayList adjCells = FillapixUtilities.getAdjacentCells(fillapixBoard, cell); + for (FillapixCell adjCell : adjCells) { + if (adjCell.getType() == FillapixCellType.BLACK) { + numBlack++; } } + if (numBlack > cellNum) { + return null; + } + return super.getNoContradictionMessage(); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TouchingCornersDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TouchingCornersDirectRule.java new file mode 100644 index 000000000..6f4be7842 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TouchingCornersDirectRule.java @@ -0,0 +1,108 @@ +package edu.rpi.legup.puzzle.fillapix.rules; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.rules.DirectRule; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.fillapix.FillapixBoard; +import edu.rpi.legup.puzzle.fillapix.FillapixCell; +import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; + +public class TouchingCornersDirectRule extends DirectRule { + public TouchingCornersDirectRule() { + super("FPIX-BASC-0005", + "Touching Corners", + "Clues with touching corners have the same difference in black cells in their unshared regions as the difference in their numbers", + "edu/rpi/legup/images/fillapix/rules/TouchingCorners.png"); + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + FillapixBoard board = (FillapixBoard) transition.getBoard(); + FillapixBoard parentBoard = (FillapixBoard) transition.getParents().get(0).getBoard().copy(); + FillapixCell cell = (FillapixCell) board.getPuzzleElement(puzzleElement); + FillapixCell parentCell = (FillapixCell) parentBoard.getPuzzleElement(puzzleElement); + + // cell has to have been empty before + if (parentCell.getType() != FillapixCellType.UNKNOWN) { + return super.getInvalidUseOfRuleMessage(); + } + + // parentBoard cannot have any contradictions + if (FillapixUtilities.checkBoardForContradiction(parentBoard)) { + return super.getInvalidUseOfRuleMessage(); + } + + // get all adjCells that have a number + ArrayList adjCells = FillapixUtilities.getAdjacentCells(parentBoard, parentCell); + adjCells.removeIf(x -> x.getNumber() < 0 || x.getNumber() >= 10); + /* remove any number cell that does not have another number cell diagonally + * adjacent to it on the opposite side of the modified cell */ + Iterator itr = adjCells.iterator(); + while (itr.hasNext()) { + FillapixCell adjCell = itr.next(); + + boolean found = false; + ArrayList adjAdjCells = FillapixUtilities.getAdjacentCells(parentBoard, adjCell); + for (FillapixCell adjAdjCell : adjAdjCells) { + if (adjAdjCell.getLocation().x != adjCell.getLocation().x && + adjAdjCell.getLocation().y != adjCell.getLocation().y && + adjAdjCell.getNumber() >= 0 && adjAdjCell.getNumber() < 10 && + adjAdjCell.getIndex() != parentCell.getIndex()) { + // adjAdjCell is diagonally adjacent to adjCell && it has a + // number && it is not parentCell + found = true; + } + } + + // does not qualify for this rule + if (!found) { + itr.remove(); + } + } + + // change the cell to the opposite color + if (cell.getType() == FillapixCellType.BLACK) { + parentCell.setCellType(FillapixCellType.WHITE); + } + else { + parentCell.setCellType(FillapixCellType.BLACK); + } + // check for some contradiction in all cases + parentBoard.addModifiedData(parentCell); + CaseRule completeClue = new SatisfyClueCaseRule(); + List caseBoards; + for (FillapixCell adjCell : adjCells) { + caseBoards = completeClue.getCases(parentBoard, adjCell); + boolean found = true; + for (Board b : caseBoards) { + if (!FillapixUtilities.checkBoardForContradiction((FillapixBoard) b)) { + found = false; + } + } + if (found) { + return null; + } + } + + return super.getInvalidUseOfRuleMessage(); + } + + /** + * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * + * @param node tree node used to create default transition board + * @return default board or null if this rule cannot be applied to this tree node + */ + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TouchingSidesDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TouchingSidesDirectRule.java new file mode 100644 index 000000000..bd6dd0169 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/TouchingSidesDirectRule.java @@ -0,0 +1,115 @@ +package edu.rpi.legup.puzzle.fillapix.rules; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.rules.DirectRule; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.fillapix.FillapixBoard; +import edu.rpi.legup.puzzle.fillapix.FillapixCell; +import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.FillapixUtilities; + +public class TouchingSidesDirectRule extends DirectRule { + public TouchingSidesDirectRule() { + super("FPIX-BASC-0004", + "Touching Sides", + "Clues with touching sides have the same difference in black cells in their unshared regions as the difference in their numbers", + "edu/rpi/legup/images/fillapix/rules/TouchingSides.png"); + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + FillapixBoard board = (FillapixBoard) transition.getBoard(); + FillapixBoard parentBoard = (FillapixBoard) transition.getParents().get(0).getBoard().copy(); + FillapixCell cell = (FillapixCell) board.getPuzzleElement(puzzleElement); + FillapixCell parentCell = (FillapixCell) parentBoard.getPuzzleElement(puzzleElement); + + // cell has to have been empty before + if (parentCell.getType() != FillapixCellType.UNKNOWN) { + return super.getInvalidUseOfRuleMessage(); + } + + // parentBoard cannot have any contradictions + if (FillapixUtilities.checkBoardForContradiction(parentBoard)) { + return super.getInvalidUseOfRuleMessage(); + } + + // get all adjCells that have a number + ArrayList adjCells = FillapixUtilities.getAdjacentCells(parentBoard, parentCell); + adjCells.removeIf(x -> x.getNumber() < 0 || x.getNumber() >= 10); + /* remove any number cell that does not have another number cell adjacent + * to it on the opposite side of the modified cell */ + Iterator itr = adjCells.iterator(); + while (itr.hasNext()) { + // calculate x and y offset of adjCell from cell + FillapixCell adjCell = itr.next(); + int xOffset = adjCell.getLocation().x - cell.getLocation().x; + int yOffset = adjCell.getLocation().y - cell.getLocation().y; + + boolean found = false; + // check vertically for numbered cell in opposite direction of cell + if (adjCell.getLocation().x + xOffset >= 0 && adjCell.getLocation().x < parentBoard.getWidth()) { + int adjNum = parentBoard.getCell(adjCell.getLocation().x + xOffset, adjCell.getLocation().y).getNumber(); + if (adjNum >= 0 && adjNum < 10) { + found = true; + } + } + // check horizontally for numbered cell in opposite direction of cell + if (adjCell.getLocation().y + yOffset >= 0 && adjCell.getLocation().y < parentBoard.getHeight()) { + int adjNum = parentBoard.getCell(adjCell.getLocation().x, adjCell.getLocation().y + yOffset).getNumber(); + if (adjNum >= 0 && adjNum < 10) { + found = true; + } + } + + // if no horizontally or vertically adjacent cell on opposite side of 'cell' has number, + // then adjCell is not valid, so should be removed + if (!found) { + itr.remove(); + } + } + + // change the cell to the opposite color + if (cell.getType() == FillapixCellType.BLACK) { + parentCell.setCellType(FillapixCellType.WHITE); + } + else { + parentCell.setCellType(FillapixCellType.BLACK); + } + // check for some contradiction in all cases + parentBoard.addModifiedData(parentCell); + CaseRule completeClue = new SatisfyClueCaseRule(); + List caseBoards; + for (FillapixCell adjCell : adjCells) { + caseBoards = completeClue.getCases(parentBoard, adjCell); + boolean found = true; + for (Board b : caseBoards) { + if (!FillapixUtilities.checkBoardForContradiction((FillapixBoard) b)) { + found = false; + } + } + if (found) { + return null; + } + } + + return super.getInvalidUseOfRuleMessage(); + } + + /** + * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * + * @param node tree node used to create default transition board + * @return default board or null if this rule cannot be applied to this tree node + */ + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/fillapix_reference_sheet.txt b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/fillapix_reference_sheet.txt index b6172e7fb..2e3c96a86 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/fillapix_reference_sheet.txt +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/fillapix_reference_sheet.txt @@ -1,7 +1,11 @@ FPIX-BASC-0001 : FinishWithBlackDirectRule FPIX-BASC-0002 : FinishWithWhiteDirectRule +FPIX-BASC-0003 : MirrorDirectRule +FPIX-BASC-0004 : TouchingSidesDirectRule +FPIX-BASC-0005 : TouchingCornersDirectRule FPIX-CONT-0001 : TooFewBlackCellsContradictionRule FPIX-CONT-0002 : TooManyBlackCellsContradictionRule -FPIX-CASE-0001 : BlackOrWhiteCaseRule \ No newline at end of file +FPIX-CASE-0001 : BlackOrWhiteCaseRule +FPIX-CASE-0002 : CompleteClueCaseRule \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java index 1f166685b..cf7b70ccd 100644 --- a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java @@ -287,4 +287,67 @@ private List getAdjacentCells(LightUpBoard board, LightUpCell cell) } return cells; } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = new ArrayList<>(); + + LightUpBoard puzzleBoard = (LightUpBoard) board; + LightUpCell point = (LightUpCell)puzzleBoard.getPuzzleElement(puzzleElement); + + List cells = getAdjacentCells(puzzleBoard,point); + + for (LightUpCell cell : cells) { + //add cells that can light adjacents from any direction + Point location = cell.getLocation(); + for (int i = location.x; i < puzzleBoard.getWidth(); i++) { + System.out.println(i); + LightUpCell c = puzzleBoard.getCell(i, location.y); + if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) { + break; + } + else if (!elements.contains(board.getPuzzleElement(c))) { + elements.add(board.getPuzzleElement(c)); + } + } + for (int i = location.x; i >= 0; i--) { + LightUpCell c = puzzleBoard.getCell(i, location.y); + if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) { + break; + } + else if (!elements.contains(board.getPuzzleElement(c))) { + elements.add(board.getPuzzleElement(c)); + } + } + for (int i = location.y; i < puzzleBoard.getHeight(); i++) { + LightUpCell c = puzzleBoard.getCell(location.x, i); + if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) { + break; + } + else if (!elements.contains(board.getPuzzleElement(c))) { + elements.add(board.getPuzzleElement(c)); + } + } + for (int i = location.y; i >= 0; i--) { + LightUpCell c = puzzleBoard.getCell(location.x, i); + if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) { + break; + } + else if (!elements.contains(board.getPuzzleElement(c))) { + elements.add(board.getPuzzleElement(c)); + } + } + } + + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/SurroundRegionDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/SurroundRegionDirectRule.java index b77f8a79f..d992fd22c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/SurroundRegionDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/SurroundRegionDirectRule.java @@ -3,12 +3,20 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.rules.DirectRule; -import edu.rpi.legup.model.rules.ContradictionRule; import edu.rpi.legup.model.tree.TreeNode; import edu.rpi.legup.model.tree.TreeTransition; import edu.rpi.legup.puzzle.nurikabe.NurikabeBoard; import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; import edu.rpi.legup.puzzle.nurikabe.NurikabeType; +import edu.rpi.legup.puzzle.nurikabe.NurikabeUtilities; +import edu.rpi.legup.utility.DisjointSets; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.HashSet; +import java.util.Set; +import java.awt.*; public class SurroundRegionDirectRule extends DirectRule { @@ -29,7 +37,6 @@ public SurroundRegionDirectRule() { */ @Override public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { - ContradictionRule contraRule = new TooManySpacesContradictionRule(); NurikabeBoard destBoardState = (NurikabeBoard) transition.getBoard(); NurikabeBoard origBoardState = (NurikabeBoard) transition.getParents().get(0).getBoard(); @@ -44,12 +51,35 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem NurikabeCell modCell = (NurikabeCell) modified.getPuzzleElement(puzzleElement); modCell.setData(NurikabeType.WHITE.toValue()); - if (contraRule.checkContradiction(modified) == null) { - return null; - } - else { - return "Does not follow from this rule at this index"; + if(cell.getType() == NurikabeType.BLACK) { + DisjointSets regions = NurikabeUtilities.getNurikabeRegions(destBoardState); + Set adj = new HashSet<>(); //set to hold adjacent cells + Point loc = cell.getLocation(); //position of placed cell + List directions = Arrays.asList(new Point(-1, 0), new Point(1, 0), new Point(0, -1), new Point(0, 1)); + for(Point direction : directions) { + NurikabeCell curr = destBoardState.getCell(loc.x + direction.x, loc.y + direction.y); + if(curr != null) { + if(curr.getType() == NurikabeType.WHITE || curr.getType() == NurikabeType.NUMBER) { + adj.add(curr); //adds cells to adj only if they are white or number blocks + } + } + } + List numberedCells = new ArrayList<>(); //number value of number cells + for (NurikabeCell c : adj) { //loops through adjacent cells + Set disRow = regions.getSet(c); //set of white spaces + for (NurikabeCell d : disRow) { //loops through white spaces + if (d.getType() == NurikabeType.NUMBER) { //if the white space is a number + numberedCells.add(d); //add that number to numberedCells + } + } + } + for (NurikabeCell number : numberedCells) { //loops through numberedCells + if (regions.getSet(number).size() == number.getData()) { //if that cells white area is the exact + return null; //size of the number of one of the number cells within that set + } + } } + return "Does not follow from this rule at this index"; } /** diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java index 380afb4cd..bc713d407 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java @@ -1,61 +1,57 @@ -package edu.rpi.legup.puzzle.shorttruthtable; - -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; - -public class ShortTruthTableOperation { - - public static final char AND = '^'; - public static final char OR = '|'; - public static final char NOT = '~'; - public static final char CONDITIONAL = '>'; - public static final char BICONDITIONAL = '-'; - - private ShortTruthTableOperation() { - } - - - public static String getLogicSymbol(char c) { - switch (c) { - case AND: - return "\u2227"; - case OR: - return "\u2228"; - case NOT: - return "\u00AC"; - case CONDITIONAL: - return "\u2192"; - case BICONDITIONAL: - return "\u2194"; - } - return "" + c; - } - - public static String getRuleName(char operation) { - switch (operation) { - case AND: - return "And"; - case OR: - return "Or"; - case NOT: - return "Not"; - case CONDITIONAL: - return "Conditional"; - case BICONDITIONAL: - return "Biconditional"; - } - return null; - } - - - public static boolean isOperation(char c) { - return c == AND || - c == OR || - c == NOT || - c == CONDITIONAL || - c == BICONDITIONAL; - } - - -} +package edu.rpi.legup.puzzle.shorttruthtable; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +public class ShortTruthTableOperation { + + public static final char AND = '^'; + public static final char OR = '|'; + public static final char NOT = '~'; + public static final char CONDITIONAL = '>'; + public static final char BICONDITIONAL = '-'; + + private ShortTruthTableOperation() { + } + + public static String getLogicSymbol(char c) { + switch (c) { + case AND: + return "\u2227"; + case OR: + return "\u2228"; + case NOT: + return "\u00AC"; + case CONDITIONAL: + return "\u2192"; + case BICONDITIONAL: + return "\u2194"; + } + return "" + c; + } + + public static String getRuleName(char operation) { + switch (operation) { + case AND: + return "And"; + case OR: + return "Or"; + case NOT: + return "Not"; + case CONDITIONAL: + return "Conditional"; + case BICONDITIONAL: + return "Biconditional"; + } + return null; + } + + public static boolean isOperation(char c) { + return c == AND || + c == OR || + c == NOT || + c == CONDITIONAL || + c == BICONDITIONAL; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/DirectRule_Generic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/DirectRule_Generic.java index a9b9ab651..e1ac78b8c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/DirectRule_Generic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/DirectRule_Generic.java @@ -22,6 +22,8 @@ public DirectRule_Generic(String ruleID, String ruleName, String description, St } public String checkRuleRawAt(TreeTransition transition, PuzzleElement element) { + // Rule must have cell to evaluate on + if (element == null) return super.getInvalidUseOfRuleMessage() + ": Must have painted cell"; // Check that the puzzle element is not unknown ShortTruthTableBoard parentBoard = (ShortTruthTableBoard) transition.getParents().get(0).getBoard(); diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java index ddc84df16..12fac9c4c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java @@ -1,23 +1,23 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - -public class CaseRuleAnd extends CaseRule_GenericStatement { - - public CaseRuleAnd() { - super("STTT-CASE-0001", ShortTruthTableOperation.AND, - "And", - trueCases, - falseCases); - } - - private static final ShortTruthTableCellType[][] trueCases = { - {T, T} - }; - private static final ShortTruthTableCellType[][] falseCases = { - {F, N}, - {N, F} - }; - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + +public class CaseRuleAnd extends CaseRule_GenericStatement { + + public CaseRuleAnd() { + super("STTT-CASE-0001", ShortTruthTableOperation.AND, + "And", + trueCases, + falseCases); + } + + private static final ShortTruthTableCellType[][] trueCases = { + {T, T} + }; + private static final ShortTruthTableCellType[][] falseCases = { + {F, U}, + {U, F} + }; + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java index 9b2ef7fea..f168499cc 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java @@ -20,7 +20,6 @@ public CaseRuleAtomic() { super("STTT-CASE-0002", "Atomic", "True or False", "Each unknown cell must either be true or false"); - System.out.println("Case Rule T/F constructor"); } // Adds all elements that can be selected for this case rule diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java index 867708729..a9fee2b4e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java @@ -1,23 +1,23 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - -public class CaseRuleConditional extends CaseRule_GenericStatement { - - public CaseRuleConditional() { - super("STTT-CASE-0004", ShortTruthTableOperation.CONDITIONAL, - "Conditional", - trueCases, - falseCases); - } - - private static final ShortTruthTableCellType[][] trueCases = { - {N, T}, - {F, N} - }; - private static final ShortTruthTableCellType[][] falseCases = { - {T, F}, - }; - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + +public class CaseRuleConditional extends CaseRule_GenericStatement { + + public CaseRuleConditional() { + super("STTT-CASE-0004", ShortTruthTableOperation.CONDITIONAL, + "Conditional", + trueCases, + falseCases); + } + + private static final ShortTruthTableCellType[][] trueCases = { + {U, T}, + {F, U} + }; + private static final ShortTruthTableCellType[][] falseCases = { + {T, F}, + }; + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java index e0bc9774c..82f814cc8 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java @@ -1,23 +1,23 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - -public class CaseRuleOr extends CaseRule_GenericStatement { - - public CaseRuleOr() { - super("STTT-CASE-0005", ShortTruthTableOperation.OR, - "Or", - trueCases, - falseCases); - } - - private static final ShortTruthTableCellType[][] trueCases = { - {T, N}, - {N, T} - }; - private static final ShortTruthTableCellType[][] falseCases = { - {F, F}, - }; - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + +public class CaseRuleOr extends CaseRule_GenericStatement { + + public CaseRuleOr() { + super("STTT-CASE-0005", ShortTruthTableOperation.OR, + "Or", + trueCases, + falseCases); + } + + private static final ShortTruthTableCellType[][] trueCases = { + {T, U}, + {U, T} + }; + private static final ShortTruthTableCellType[][] falseCases = { + {F, F}, + }; + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java index 047ea5d33..1409f4baa 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java @@ -1,73 +1,71 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.gameboard.CaseBoard; -import edu.rpi.legup.model.gameboard.PuzzleElement; -import edu.rpi.legup.model.rules.CaseRule; -import edu.rpi.legup.model.tree.TreeTransition; - -import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; -import edu.rpi.legup.puzzle.nurikabe.NurikabeType; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - - -import java.util.ArrayList; -import java.util.List; - -public abstract class CaseRule_Generic extends CaseRule { - - public CaseRule_Generic(String ruleID, String ruleName, String title, String description) { - super(ruleID, title, description, "edu/rpi/legup/images/shorttruthtable/ruleimages/case/" + ruleName + ".png"); - } - - - /** - * Checks whether the transition logically follows from the parent node using this rule - * - * @param transition transition to check - * @return null if the child node logically follow from the parent node, otherwise error message - */ - @Override - public String checkRuleRaw(TreeTransition transition) { - List childTransitions = transition.getParents().get(0).getChildren(); - if (childTransitions.size() != 2) { - return "This case rule must have 2 children."; - } - - TreeTransition case1 = childTransitions.get(0); - TreeTransition case2 = childTransitions.get(1); - if (case1.getBoard().getModifiedData().size() != 1 || case2.getBoard().getModifiedData().size() != 1) { - return "This case rule must have 1 modified cell for each case."; - } - - ShortTruthTableCell mod1 = (ShortTruthTableCell) case1.getBoard().getModifiedData().iterator().next(); - ShortTruthTableCell mod2 = (ShortTruthTableCell) case2.getBoard().getModifiedData().iterator().next(); - if (!mod1.getLocation().equals(mod2.getLocation())) { - return "This case rule must modify the same cell for each case."; - } - - boolean firstPossibility = mod1.getType() == ShortTruthTableCellType.TRUE && mod2.getType() == ShortTruthTableCellType.FALSE; - boolean secondPossibility = mod1.getType() == ShortTruthTableCellType.FALSE && mod2.getType() == ShortTruthTableCellType.TRUE; - if (!firstPossibility && !secondPossibility) { - return "This case rule must an empty true or false cell."; - } - - return null; - } - - /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule - * - * @param transition transition to check - * @param puzzleElement equivalent puzzleElement - * @return null if the child node logically follow from the parent node at the specified puzzleElement, - * otherwise error message - */ - @Override - public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { - return checkRuleRaw(transition); - } -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.CaseBoard; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.tree.TreeTransition; + +import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; +import edu.rpi.legup.puzzle.nurikabe.NurikabeType; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.JOptionPane; + +import com.google.firebase.database.core.utilities.Tree; + +public abstract class CaseRule_Generic extends CaseRule { + + public CaseRule_Generic(String ruleID, String ruleName, String title, String description) { + super(ruleID, title, description, "edu/rpi/legup/images/shorttruthtable/ruleimages/case/" + ruleName + ".png"); + } + + + /** + * Checks whether the transition logically follows from the parent node using this rule + * + * @param transition transition to check + * @return null if the child node logically follow from the parent node, otherwise error message + */ + @Override + public String checkRuleRaw(TreeTransition transition) { + // Validate that two children are generated + List childTransitions = transition.getParents().get(0).getChildren(); + if (childTransitions.size() >= 1) { + return "ERROR: This case rule must spawn at least 1 child."; + } + + // Validate that the modified cells are of type UNKNOWN, TRUE, or FALSE + List cases = Arrays.asList(childTransitions.get(0), childTransitions.get(1)); + for (TreeTransition c : cases) { + ShortTruthTableCell mod1 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); + ShortTruthTableCell mod2 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); + if (!(mod1.getType() == ShortTruthTableCellType.TRUE || mod1.getType() == ShortTruthTableCellType.FALSE || mod1.getType() == ShortTruthTableCellType.UNKNOWN) && + (mod2.getType() == ShortTruthTableCellType.TRUE || mod2.getType() == ShortTruthTableCellType.FALSE || mod2.getType() == ShortTruthTableCellType.UNKNOWN)) { + return "ERROR: This case rule must be an unknown, true, or false cell."; + } + } + return null; + } + + /** + * Checks whether the child node logically follows from the parent node + * at the specific puzzleElement index using this rule + * + * @param transition transition to check + * @param puzzleElement equivalent puzzleElement + * @return null if the child node logically follow from the parent node at the specified puzzleElement, + * otherwise error message + */ + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + return checkRuleRaw(transition); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java index 375a60292..0e25586a8 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java @@ -10,7 +10,7 @@ import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableStatement; import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; - +import java.util.List; import java.util.ArrayList; public abstract class CaseRule_GenericStatement extends CaseRule_Generic { @@ -35,9 +35,9 @@ public CaseRule_GenericStatement(String ruleID, char operation, String title, protected static final ShortTruthTableCellType T = ShortTruthTableCellType.TRUE; protected static final ShortTruthTableCellType F = ShortTruthTableCellType.FALSE; - protected static final ShortTruthTableCellType N = null; + protected static final ShortTruthTableCellType U = ShortTruthTableCellType.UNKNOWN; - //Adds all elements that can be selected for this caserule + // Adds all elements that can be selected for this caserule @Override public CaseBoard getCaseBoard(Board board) { //copy the board and add all elements that can be selected @@ -47,31 +47,19 @@ public CaseBoard getCaseBoard(Board board) { //add all elements that can be selected for the case rule statement for (PuzzleElement element : sttBoard.getPuzzleElements()) { - - System.out.println("GetCaseBoard Testing: " + element); - //get the cell object ShortTruthTableCell cell = sttBoard.getCellFromElement(element); //the cell must match the symbol if (cell.getSymbol() != this.operation) continue; - - System.out.println(" Selectable... checking logic"); - //the statement must be assigned with unassigned sub-statements if (!cell.getType().isTrueOrFalse()) continue; - System.out.println(" Operation is known"); if (cell.getStatementReference().getRightStatement().getCell().getType().isTrueOrFalse()) continue; - System.out.println(" right side is unknown"); if (this.operation != ShortTruthTableOperation.NOT && cell.getStatementReference().getRightStatement().getCell().getType().isTrueOrFalse()) { continue; } - System.out.println(" left side is unknown"); - - System.out.println(" Valid choice"); //if the element has passed all the checks, it can be selected caseBoard.addPickableElement(element); - } return caseBoard; } @@ -86,57 +74,64 @@ public CaseBoard getCaseBoard(Board board) { @SuppressWarnings("unchecked") @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { - ShortTruthTableBoard sttBoard = ((ShortTruthTableBoard) board); - ShortTruthTableCell cell = sttBoard.getCellFromElement(puzzleElement); - //if the statement is set to true + // If the statement is set to true, collect true cases. Otherwise, collect the false cases if (cell.getType() == ShortTruthTableCellType.TRUE) { return getCasesFromCell(sttBoard, puzzleElement, trueCases); } - - //if the statement is set to false return getCasesFromCell(sttBoard, puzzleElement, falseCases); - } + /** + * Collects a list of boards for each possible outcome of case-rule application + * @param board current board state + * @param puzzleElement case rule operator + * @param possibilities list of possibilities for operator state + * @return ArrayList of Boards + */ private ArrayList getCasesFromCell(ShortTruthTableBoard board, PuzzleElement puzzleElement, ShortTruthTableCellType[][] possibilities) { - - //store all possible boards + // Create branch case for each possibility ArrayList cases = new ArrayList<>(); - - //go through all the possibilities for (int i = 0; i < possibilities.length; i++) { - //create a new board + // Create a new board to modify and get statement of selected square ShortTruthTableBoard b = board.copy(); - - //get the statement of the square that was selected ShortTruthTableCell cell = b.getCellFromElement(puzzleElement); ShortTruthTableStatement statement = cell.getStatementReference(); - //modify its children - //avoid error if it is a NOT statement - if (possibilities[i][0] != null) { + // Modify neighboring cells of case-rule application by the provided logical cases + if (possibilities[i][0] != ShortTruthTableCellType.UNKNOWN) { ShortTruthTableCell leftCell = statement.getLeftStatement().getCell(); leftCell.setData(possibilities[i][0]); b.addModifiedData(leftCell); } - - //always modify the right side of the statement - if (possibilities[i][1] != null) { + if (possibilities[i][1] != ShortTruthTableCellType.UNKNOWN) { ShortTruthTableCell rightCell = statement.getRightStatement().getCell(); rightCell.setData(possibilities[i][1]); b.addModifiedData(rightCell); } - //add the board possibility to the list cases.add(b); } - - //return all possibilities return cases; - } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = super.dependentElements(board,puzzleElement); + + elements.add(board.getPuzzleElement(puzzleElement)); + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java index ca6bcbe02..52e8a6400 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java @@ -25,9 +25,6 @@ public class SkyscrapersBoard extends GridBoard { private boolean viewFlag = false; private boolean dupeFlag = false; - private SkyscrapersClue modClue = null; - //helper variable for case rule verification, tracks recently modified row/col - public SkyscrapersBoard(int size) { super(size, size); @@ -94,14 +91,6 @@ public void setViewFlag(boolean newFlag) { viewFlag = newFlag; } - public SkyscrapersClue getmodClue() { - return modClue; - } - - public void setModClue(SkyscrapersClue newClue) { - modClue = newClue; - } - @Override public SkyscrapersCell getCell(int x, int y) { return (SkyscrapersCell) super.getCell(x, y); diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java index dc68f45c7..1e7b1b45e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java @@ -47,6 +47,9 @@ public void setType(SkyscrapersType type) { } public SkyscrapersClue copy() { - return null; + SkyscrapersClue copy = new SkyscrapersClue(data, clueIndex, type); + copy.setIndex(index); + copy.setModifiable(isModifiable); + return copy; } } diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java index 683b742bf..01527294a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java @@ -69,7 +69,6 @@ public ArrayList getCasesFor(Board board, PuzzleElement puzzleElement, In PuzzleElement newCell = newCase.getPuzzleElement(cell); newCell.setData(number); newCase.addModifiedData(newCell); - newCase.setModClue((SkyscrapersClue) newCase.getPuzzleElement(clue)); //if flags boolean passed = true; @@ -103,12 +102,7 @@ public String checkRuleRaw(TreeTransition transition) { return "This case rule must have at least one child."; } - //find changed row/col - SkyscrapersClue modClue = ((SkyscrapersBoard) childTransitions.get(0).getBoard()).getmodClue(); - - //System.out.println(modClue.getType()); - //System.out.println(modClue.getClueIndex()); - if (childTransitions.size() != getCasesFor(oldBoard, modClue, (Integer) childTransitions.get(0).getBoard().getModifiedData().iterator().next().getData()).size()) { + if (childTransitions.size() != getCasesFor(oldBoard, oldBoard.getPuzzleElement(transition.getSelection()), (Integer) childTransitions.get(0).getBoard().getModifiedData().iterator().next().getData()).size()) { //System.out.println("Wrong number of cases."); return "Wrong number of cases."; } @@ -132,4 +126,49 @@ public String checkRuleRaw(TreeTransition transition) { public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { return checkRuleRaw(transition); } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = new ArrayList<>(); + + SkyscrapersBoard puzzleBoard = (SkyscrapersBoard) board; + SkyscrapersClue clue = (SkyscrapersClue)puzzleBoard.getPuzzleElement(puzzleElement); + + // check each point in modified row/col + List data = puzzleBoard.getRowCol(clue.getClueIndex(),SkyscrapersType.ANY,clue.getType() == SkyscrapersType.CLUE_WEST); + for (SkyscrapersCell point : data) { + List cells = new ArrayList<>(List.of(point)); + + // if dependent on row/col + if ((puzzleBoard.getDupeFlag() || puzzleBoard.getViewFlag()) && point.getType() == SkyscrapersType.UNKNOWN) { + // get perpendicular row/col intersecting this point + int index; + if (clue.getType() == SkyscrapersType.CLUE_WEST) { + index = point.getLocation().x; + } + else { + index = point.getLocation().y; + } + cells.addAll(puzzleBoard.getRowCol(index,SkyscrapersType.ANY,clue.getType() != SkyscrapersType.CLUE_WEST)); + } + + // add all to result + for (SkyscrapersCell cell : cells) { + if (!elements.contains(board.getPuzzleElement(cell))) { + elements.add(board.getPuzzleElement(cell)); + } + } + } + + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java index a061c62a3..3bf0de70a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java @@ -7,6 +7,7 @@ import edu.rpi.legup.model.tree.TreeTransition; import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersBoard; import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell; +import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersClue; import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType; import java.awt.*; @@ -134,4 +135,38 @@ public String checkRuleRaw(TreeTransition transition) { public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { return checkRuleRaw(transition); } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = new ArrayList<>(); + + SkyscrapersBoard puzzleBoard = (SkyscrapersBoard) board; + SkyscrapersCell point = (SkyscrapersCell)puzzleBoard.getPuzzleElement(puzzleElement); + + List cells = new ArrayList<>(List.of(point)); + + // if dependent on row/col + if (puzzleBoard.getDupeFlag() || puzzleBoard.getViewFlag()) { + // add all cells in row/col intersecting given point + cells.addAll(puzzleBoard.getRowCol(point.getLocation().x,SkyscrapersType.ANY,false)); + cells.addAll(puzzleBoard.getRowCol(point.getLocation().y,SkyscrapersType.ANY,true)); + } + + for (SkyscrapersCell cell : cells) { + if (!elements.contains(board.getPuzzleElement(cell))) { + elements.add(board.getPuzzleElement(cell)); + } + } + + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java index 2542ea335..dc809f34d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java @@ -124,21 +124,11 @@ public void notifyDeletion(PuzzleElement puzzleElement) { public List getAdjacent(TreeTentCell cell, TreeTentType type) { List adj = new ArrayList<>(); Point loc = cell.getLocation(); - TreeTentCell up = getCell(loc.x, loc.y - 1); - TreeTentCell right = getCell(loc.x + 1, loc.y); - TreeTentCell down = getCell(loc.x, loc.y + 1); - TreeTentCell left = getCell(loc.x - 1, loc.y); - if (up != null && up.getType() == type) { - adj.add(up); - } - if (right != null && right.getType() == type) { - adj.add(right); - } - if (down != null && down.getType() == type) { - adj.add(down); - } - if (left != null && left.getType() == type) { - adj.add(left); + for (int i = -2; i < 2; i++) { + TreeTentCell adjCell = getCell(loc.x + (i % 2), loc.y + ((i + 1) % 2)); + if (adjCell != null && adjCell.getType() == type) { + adj.add(adjCell); + } } return adj; } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCell.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCell.java index 290e0858d..b6411a5cf 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCell.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCell.java @@ -16,15 +16,31 @@ public TreeTentType getType() { return data; } + public int getValue() { + switch (data) { + case TREE: + return 1; + case GRASS: + return 2; + case TENT: + return 3; + default: + return 0; + } + } + @Override public void setType(Element e, MouseEvent m) { switch (e.getElementName()) { case "Unknown Tile": this.data = TreeTentType.UNKNOWN; + break; case "Tree Tile": this.data = TreeTentType.TREE; + break; case "Grass Tile": this.data = TreeTentType.GRASS; + break; case "Tent Tile": this.data = TreeTentType.TENT; } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCellFactory.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCellFactory.java index 969ffdf0f..20b8066a4 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCellFactory.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCellFactory.java @@ -83,7 +83,7 @@ public org.w3c.dom.Element exportCell(Document document, PuzzleElement puzzleEle TreeTentCell cell = (TreeTentCell) puzzleElement; Point loc = cell.getLocation(); - cellElement.setAttribute("value", String.valueOf(cell.getData())); + cellElement.setAttribute("value", String.valueOf(cell.getValue())); cellElement.setAttribute("x", String.valueOf(loc.x)); cellElement.setAttribute("y", String.valueOf(loc.y)); diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java index 2b969b4bb..1f431594c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java @@ -29,83 +29,83 @@ public TreeTentController() { this.lastCellPressed = null; } -// @Override -// public void mousePressed(MouseEvent e) { -// if (e.getButton() != MouseEvent.BUTTON2) { -// BoardView boardView = getInstance().getLegupUI().getBoardView(); -// dragStart = boardView.getElement(e.getPoint()); -// lastCellPressed = boardView.getElement(e.getPoint()); -// } -// } + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON2) { + BoardView boardView = getInstance().getLegupUI().getBoardView(); + dragStart = boardView.getElement(e.getPoint()); + lastCellPressed = boardView.getElement(e.getPoint()); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (GameBoardFacade.getInstance().getLegupUI().getTreePanel() != null && e.getButton() != MouseEvent.BUTTON2) { + TreePanel treePanel = GameBoardFacade.getInstance().getLegupUI().getTreePanel(); + TreeView treeView = GameBoardFacade.getInstance().getLegupUI().getTreePanel().getTreeView(); + BoardView boardView = getInstance().getLegupUI().getBoardView(); + lastCellPressed = boardView.getElement(e.getPoint()); + Board board = boardView.getBoard(); + TreeViewSelection selection = treeView.getSelection(); -// @Override -// public void mouseReleased(MouseEvent e) { -// if (GameBoardFacade.getInstance().getLegupUI().getTreePanel() != null && e.getButton() != MouseEvent.BUTTON2) { -// TreePanel treePanel = GameBoardFacade.getInstance().getLegupUI().getTreePanel(); -// TreeView treeView = GameBoardFacade.getInstance().getLegupUI().getTreePanel().getTreeView(); -// BoardView boardView = getInstance().getLegupUI().getBoardView(); -// lastCellPressed = boardView.getElement(e.getPoint()); -// Board board = boardView.getBoard(); -// TreeViewSelection selection = treeView.getSelection(); -// -// if (dragStart != null) { -// if (board instanceof CaseBoard) { -// CaseBoard caseBoard = (CaseBoard) board; -// AutoCaseRuleCommand autoCaseRuleCommand = new AutoCaseRuleCommand(dragStart, selection, caseBoard.getCaseRule(), caseBoard, e); -// if (autoCaseRuleCommand.canExecute()) { -// autoCaseRuleCommand.execute(); -// getInstance().getHistory().pushChange(autoCaseRuleCommand); -// treePanel.updateError(""); -// } -// else { -// treePanel.updateError(autoCaseRuleCommand.getError()); -// } -// } -// else { -// if (dragStart == lastCellPressed) { -// if (dragStart.getPuzzleElement().getIndex() >= 0) { -// ICommand edit = new EditDataCommand(lastCellPressed, selection, e); -// if (edit.canExecute()) { -// edit.execute(); -// getInstance().getHistory().pushChange(edit); -// treePanel.updateError(""); -// } -// else { -// treePanel.updateError(edit.getError()); -// } -// } -// else { -// ClueCommand edit = new ClueCommand(selection, (TreeTentClueView) dragStart); -// if (edit.canExecute()) { -// edit.execute(); -// getInstance().getHistory().pushChange(edit); -// treePanel.updateError(""); -// } -// else { -// treePanel.updateError(edit.getError()); -// } -// } -// } -// else { -// if (lastCellPressed != null) { -// if (dragStart instanceof TreeTentElementView) { -// ICommand editLine = new EditLineCommand(selection, (TreeTentElementView) dragStart, lastCellPressed); -// if (editLine.canExecute()) { -// editLine.execute(); -// getInstance().getHistory().pushChange(editLine); -// } -// else { -// treePanel.updateError(editLine.getError()); -// } -// } -// } -// } -// } -// } -// dragStart = null; -// lastCellPressed = null; -// } -// } + if (dragStart != null) { + if (board instanceof CaseBoard) { + CaseBoard caseBoard = (CaseBoard) board; + AutoCaseRuleCommand autoCaseRuleCommand = new AutoCaseRuleCommand(dragStart, selection, caseBoard.getCaseRule(), caseBoard, e); + if (autoCaseRuleCommand.canExecute()) { + autoCaseRuleCommand.execute(); + getInstance().getHistory().pushChange(autoCaseRuleCommand); + treePanel.updateError(""); + } + else { + treePanel.updateError(autoCaseRuleCommand.getError()); + } + } + else { + if (dragStart == lastCellPressed) { + if (dragStart.getPuzzleElement().getIndex() >= 0) { + ICommand edit = new EditDataCommand(lastCellPressed, selection, e); + if (edit.canExecute()) { + edit.execute(); + getInstance().getHistory().pushChange(edit); + treePanel.updateError(""); + } + else { + treePanel.updateError(edit.getError()); + } + } + else { + ClueCommand edit = new ClueCommand(selection, (TreeTentClueView) dragStart); + if (edit.canExecute()) { + edit.execute(); + getInstance().getHistory().pushChange(edit); + treePanel.updateError(""); + } + else { + treePanel.updateError(edit.getError()); + } + } + } + else { + if (lastCellPressed != null) { + if (dragStart instanceof TreeTentElementView) { + ICommand editLine = new EditLineCommand(selection, (TreeTentElementView) dragStart, lastCellPressed); + if (editLine.canExecute()) { + editLine.execute(); + getInstance().getHistory().pushChange(editLine); + } + else { + treePanel.updateError(editLine.getError()); + } + } + } + } + } + } + dragStart = null; + lastCellPressed = null; + } + } @Override public void changeCell(MouseEvent e, PuzzleElement element) { diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java index 538772b74..698b3aa5e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java @@ -160,4 +160,29 @@ public String checkRuleRaw(TreeTransition transition) { public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { return null; } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = new ArrayList<>(); + + TreeTentBoard treeTentBoard = (TreeTentBoard) board; + TreeTentClue clue = (TreeTentClue) puzzleElement; + + // add all elements of filled row + for (int i = 0; i < treeTentBoard.getWidth(); i++) { + TreeTentCell cell = treeTentBoard.getCell(i, clue.getClueIndex()-1); + elements.add(board.getPuzzleElement((cell))); + } + + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java index 36f466f87..39b1d0251 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java @@ -5,7 +5,6 @@ import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.rules.CaseRule; import edu.rpi.legup.model.tree.TreeTransition; -import edu.rpi.legup.puzzle.treetent.TreeTent; import edu.rpi.legup.puzzle.treetent.TreeTentBoard; import edu.rpi.legup.puzzle.treetent.TreeTentType; import edu.rpi.legup.puzzle.treetent.TreeTentCell; @@ -151,4 +150,18 @@ public String checkRuleRaw(TreeTransition transition) { public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { return checkRuleRaw(transition); } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + return List.of(board.getPuzzleElement(puzzleElement)); + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java index 249547301..72ffd62eb 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java @@ -10,6 +10,7 @@ import edu.rpi.legup.puzzle.treetent.TreeTentLine; import edu.rpi.legup.puzzle.treetent.TreeTentType; +import java.awt.Point; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -152,4 +153,32 @@ public String checkRuleRaw(TreeTransition transition) { public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { return checkRuleRaw(transition); } + + /** + * Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid + * Overridden by case rules dependent on more than just the modified data + * + * @param board board state at application + * @param puzzleElement selected puzzleElement + * @return List of puzzle elements (typically cells) this application of the case rule depends upon. + * Defaults to any element modified by any case + */ + @Override + public List dependentElements(Board board, PuzzleElement puzzleElement) { + List elements = new ArrayList<>(List.of(board.getPuzzleElement(puzzleElement))); + + TreeTentBoard treeTentBoard = (TreeTentBoard) board; + TreeTentCell point = (TreeTentCell) puzzleElement; + + // get all adjacent cells + Point loc = point.getLocation(); + for (int i = -2; i < 2; i++) { + TreeTentCell cell = treeTentBoard.getCell(loc.x + (i % 2), loc.y + ((i + 1) % 2)); + if (cell != null) { + elements.add(board.getPuzzleElement(cell)); + } + } + + return elements; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/SurroundTentWithGrassDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/SurroundTentWithGrassDirectRule.java index 829c1c1e9..44e9dfcc4 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/SurroundTentWithGrassDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/SurroundTentWithGrassDirectRule.java @@ -31,6 +31,9 @@ public SurroundTentWithGrassDirectRule() { */ @Override public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + if (puzzleElement == null) { + return null; + } if (puzzleElement instanceof TreeTentLine) { return super.getInvalidUseOfRuleMessage() + ": Line is not valid for this rule."; } diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java index fa08972ed..9bfffe60a 100644 --- a/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java @@ -2,7 +2,12 @@ import edu.rpi.legup.app.GameBoardFacade; import edu.rpi.legup.controller.TreeController; +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.GridCell; +import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.observer.ITreeListener; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.tree.Tree; import edu.rpi.legup.model.tree.TreeElement; import edu.rpi.legup.model.tree.TreeNode; @@ -316,6 +321,50 @@ public void onTreeElementRemoved(TreeElement element) { TreeTransition trans = (TreeTransition) element; TreeTransitionView transView = (TreeTransitionView) viewMap.get(trans); + // unlock ancestor elements if case rule deleted + Rule rule = trans.getRule(); + for (TreeNode node : trans.getParents()) { + + // only if the last case of a case rule will be deleted + if (!(rule instanceof CaseRule && node.getChildren().isEmpty())) { + continue; + } + + CaseRule caseRule = (CaseRule)rule; + // set dependent elements to be modifiable by ancestors (if not dependent on others) + List ancestors = node.getAncestors(); + for (TreeNode ancestor : ancestors) { + // for all ancestors but root + if (ancestor.getParent() == null) { + continue; + } + + for (PuzzleElement pelement : caseRule.dependentElements(node.getBoard(), trans.getSelection())) { + // decrement, unlock if 0 cases depended + PuzzleElement oldElement = ancestor.getParent().getBoard().getPuzzleElement(pelement); + oldElement.setCasesDepended(oldElement.getCasesDepended() - 1); + if (oldElement.getCasesDepended() != 0) { + continue; + } + + // set modifiable if started modifiable + boolean modifiable = tree.getRootNode().getBoard().getPuzzleElement(oldElement).isModifiable(); + + // unmodifiable if already modified + TreeNode modNode = ancestor.getParent().getParents().get(0); + while (modNode.getParent()!=null) { + Board modBoard = modNode.getParent().getBoard(); + if (modBoard.getModifiedData().contains(modBoard.getPuzzleElement(oldElement))) { + modifiable = false; + break; + } + modNode = modNode.getParent().getParents().get(0); + } + oldElement.setModifiable(modifiable); + } + } + } + transView.getParentViews().forEach(n -> n.removeChildrenView(transView)); removeTreeTransition(trans); } @@ -331,35 +380,7 @@ public void onTreeElementRemoved(TreeElement element) { public void onTreeSelectionChanged(TreeViewSelection selection) { this.selection.getSelectedViews().forEach(v -> v.setSelected(false)); selection.getSelectedViews().forEach(v -> v.setSelected(true)); - this.selection = selection; - -// List selectedViews = selection.getSelectedViews(); -// Point avg = new Point(); -// for(TreeElementView elementView : selectedViews) { -// if(elementView.getType() == NODE) { -// TreeNodeView nodeView = (TreeNodeView)elementView; -// avg.x += nodeView.getX(); -// avg.y += nodeView.getY(); -// } else { -// TreeTransitionView transitionView = (TreeTransitionView) elementView; -// avg.x += transitionView.getEndX(); -// avg.y += transitionView.getEndY(); -// } -// } -// avg.x /= selectedViews.size(); -// avg.y /= selectedViews.size(); -// -// Point pos = viewport.getViewPosition(); -// if(pos.x < avg.x) { -// pos.x = avg.x - pos.x; -// } -// if(pos.y < avg.y) { -// pos.y = avg.y - pos.y; -// } -// -// viewport.setViewPosition(pos); - repaint(); } @@ -383,6 +404,46 @@ public TreeElementView getElementView(TreeElement element) { private void removeTreeNode(TreeNode node) { viewMap.remove(node); + List children = node.getChildren(); + + // if child is a case rule, unlock ancestor elements + if (!children.isEmpty()) { + Rule rule = children.get(0).getRule(); + if (rule instanceof CaseRule) { + CaseRule caseRule = (CaseRule)rule; + // set dependent elements to be modifiable by ancestors (if not dependent on others) + List ancestors = node.getAncestors(); + for (TreeNode ancestor : ancestors) { + // for all ancestors but root + if (ancestor.getParent() == null) { + continue; + } + for (PuzzleElement pelement : caseRule.dependentElements(node.getBoard(), children.get(0).getSelection())) { + // decrement, unlock if 0 cases depended + PuzzleElement oldElement = ancestor.getParent().getBoard().getPuzzleElement(pelement); + oldElement.setCasesDepended(oldElement.getCasesDepended() - 1); + if (oldElement.getCasesDepended() == 0) { + continue; + } + + // set modifiable if started modifiable + boolean modifiable = tree.getRootNode().getBoard().getPuzzleElement(oldElement).isModifiable(); + + // unmodifiable if already modified + TreeNode modNode = ancestor.getParent().getParents().get(0); + while (modNode.getParent() != null) { + Board modBoard = modNode.getParent().getBoard(); + if (modBoard.getModifiedData().contains(modBoard.getPuzzleElement(oldElement))) { + modifiable = false; + break; + } + modNode = modNode.getParent().getParents().get(0); + } + oldElement.setModifiable(modifiable); + } + } + } + } node.getChildren().forEach(t -> removeTreeTransition(t)); } @@ -405,6 +466,27 @@ private void addTreeNode(TreeNode node) { viewMap.put(node, nodeView); if (!node.getChildren().isEmpty()) { + + // if adding a case rule, lock dependent ancestor elements + Rule rule = node.getChildren().get(0).getRule(); + if (rule instanceof CaseRule) { + CaseRule caseRule = (CaseRule)rule; + + List ancestors = node.getAncestors(); + for (TreeNode ancestor : ancestors) { + // for all ancestors but root + if (ancestor.getParent() == null) { + continue; + } + for (PuzzleElement element : caseRule.dependentElements(node.getBoard(), node.getChildren().get(0).getSelection())) { + // increment and lock + PuzzleElement oldElement = ancestor.getParent().getBoard().getPuzzleElement(element); + oldElement.setCasesDepended(oldElement.getCasesDepended()+1); + oldElement.setModifiable(false); + } + } + } + node.getChildren().forEach(t -> addTreeTransition(t)); } } @@ -417,6 +499,26 @@ private void addTreeTransition(TreeTransition trans) { TreeNodeView parentNodeView = (TreeNodeView) viewMap.get(parent); transView.addParentView(parentNodeView); parentNodeView.addChildrenView(transView); + + // if transition is a new case rule, lock dependent ancestor elements + Rule rule = trans.getRule(); + if (rule instanceof CaseRule && parent.getChildren().size()==1) { + CaseRule caseRule = (CaseRule)rule; + + List ancestors = parent.getAncestors(); + for (TreeNode ancestor : ancestors) { + // for all ancestors but root + if (ancestor.getParent() == null) { + continue; + } + for (PuzzleElement element : caseRule.dependentElements(parent.getBoard(), trans.getSelection())) { + // increment and lock + PuzzleElement oldElement = ancestor.getParent().getBoard().getPuzzleElement(element); + oldElement.setCasesDepended(oldElement.getCasesDepended()+1); + oldElement.setModifiable(false); + } + } + } } viewMap.put(trans, transView); diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/cases/BlackOrWhite.png b/src/main/resources/edu/rpi/legup/images/fillapix/cases/BlackOrWhite.png index ff234c17f..17df92f1a 100644 Binary files a/src/main/resources/edu/rpi/legup/images/fillapix/cases/BlackOrWhite.png and b/src/main/resources/edu/rpi/legup/images/fillapix/cases/BlackOrWhite.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/cases/SatisfyClue.png b/src/main/resources/edu/rpi/legup/images/fillapix/cases/SatisfyClue.png new file mode 100644 index 000000000..8d84efed9 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/cases/SatisfyClue.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooFewBlackCells.png b/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooFewBlackCells.png index b017078a2..b93d81e67 100644 Binary files a/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooFewBlackCells.png and b/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooFewBlackCells.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooManyBlackCells.png b/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooManyBlackCells.png index a0b27424d..393a8c544 100644 Binary files a/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooManyBlackCells.png and b/src/main/resources/edu/rpi/legup/images/fillapix/contradictions/TooManyBlackCells.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithBlack.png b/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithBlack.png index 41e540ad1..d098bce41 100644 Binary files a/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithBlack.png and b/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithBlack.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithWhite.png b/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithWhite.png index 330f705f1..758ca7591 100644 Binary files a/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithWhite.png and b/src/main/resources/edu/rpi/legup/images/fillapix/rules/FinishWithWhite.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/rules/Mirror.png b/src/main/resources/edu/rpi/legup/images/fillapix/rules/Mirror.png new file mode 100644 index 000000000..991408d9c Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/rules/Mirror.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/rules/NontouchingShared.png b/src/main/resources/edu/rpi/legup/images/fillapix/rules/NontouchingShared.png new file mode 100644 index 000000000..1be04f3ce Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/rules/NontouchingShared.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/rules/TouchingCorners.png b/src/main/resources/edu/rpi/legup/images/fillapix/rules/TouchingCorners.png new file mode 100644 index 000000000..f3eba46b6 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/rules/TouchingCorners.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/rules/TouchingSides.png b/src/main/resources/edu/rpi/legup/images/fillapix/rules/TouchingSides.png new file mode 100644 index 000000000..6d3b12dfd Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/rules/TouchingSides.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/tiles/BlackTile.png b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/BlackTile.png new file mode 100644 index 000000000..93e169df8 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/BlackTile.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/tiles/NumberTile.png b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/NumberTile.png new file mode 100644 index 000000000..5a8540d02 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/NumberTile.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/tiles/UnknownTile.png b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/UnknownTile.png new file mode 100644 index 000000000..850fbf127 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/UnknownTile.png differ diff --git a/src/main/resources/edu/rpi/legup/images/fillapix/tiles/WhiteTile.png b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/WhiteTile.png new file mode 100644 index 000000000..fc2c683eb Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/fillapix/tiles/WhiteTile.png differ diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config index 24fdcf365..19e63a2a3 100644 --- a/src/main/resources/edu/rpi/legup/legup/config +++ b/src/main/resources/edu/rpi/legup/legup/config @@ -7,7 +7,7 @@ + fileCreationDisabled="false"/> - \ No newline at end of file + diff --git a/src/test/java/legup/TestRunner.java b/src/test/java/legup/TestRunner.java index 9d79c590e..3a74c4c61 100644 --- a/src/test/java/legup/TestRunner.java +++ b/src/test/java/legup/TestRunner.java @@ -42,8 +42,6 @@ public static void main(String[] args) { Result result12 = JUnitCore.runClasses(TooManyBulbsContradictionRuleTest.class); printTestResults(result12); - - //nurikabe tests Result result13 = JUnitCore.runClasses(BlackBetweenRegionsDirectRuleTest.class); printTestResults(result13); @@ -76,7 +74,6 @@ public static void main(String[] args) { Result result27 = JUnitCore.runClasses(WhiteBottleNeckDirectRuleTest.class); printTestResults(result27); - // Treetent Result result28 = JUnitCore.runClasses(EmptyFieldDirectRuleTest.class); printTestResults(result28); @@ -94,6 +91,8 @@ public static void main(String[] args) { printTestResults(result34); Result result35 = JUnitCore.runClasses(TreeForTentDirectRuleTest.class); printTestResults(result35); + Result result36 = JUnitCore.runClasses(TentOrGrassCaseRuleTest.class); + printTestResults(result36); } private static void printTestResults(Result result) { diff --git a/src/test/java/puzzles/lightup/rules/BulbsInPathContradictionRuleTest.java b/src/test/java/puzzles/lightup/rules/BulbsInPathContradictionRuleTest.java index b595fec15..0e7930751 100644 --- a/src/test/java/puzzles/lightup/rules/BulbsInPathContradictionRuleTest.java +++ b/src/test/java/puzzles/lightup/rules/BulbsInPathContradictionRuleTest.java @@ -34,6 +34,7 @@ public void BulbsInPathContradictionRule_LightInHorizontalPath() throws InvalidF Assert.assertNull(RULE.checkContradictionAt(board, board.getCell(0, 0))); Assert.assertNull(RULE.checkContradictionAt(board, board.getCell(2, 0))); + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(0, 1))); } @@ -67,4 +68,19 @@ public void BulbsInPathContradictionRule_BlockInVerticalPath() throws InvalidFil Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(1, 1))); } + + @Test + public void BulbsInPathContradictionRule_BlockInHorizontalPath() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInHorizontalPath", lightUp); + TreeNode rootNode = lightUp.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + LightUpBoard board = (LightUpBoard) transition.getBoard(); + Assert.assertNotNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkContradictionAt(board,board.getCell(0,0))); + Assert.assertNotNull(RULE.checkContradictionAt(board,board.getCell(2,0))); + Assert.assertNotNull(RULE.checkContradictionAt(board,board.getCell(1,1))); + + } } diff --git a/src/test/java/puzzles/lightup/rules/CannotLightACellContradictionRuleTest.java b/src/test/java/puzzles/lightup/rules/CannotLightACellContradictionRuleTest.java index 447476dbb..7b3ffd2b9 100644 --- a/src/test/java/puzzles/lightup/rules/CannotLightACellContradictionRuleTest.java +++ b/src/test/java/puzzles/lightup/rules/CannotLightACellContradictionRuleTest.java @@ -21,13 +21,13 @@ public static void setUp() { lightUp = new LightUp(); } - @Test + @Test //extensive full testing of null and non-null in a 5x5 board public void FullLightTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/lightup/rules/CannotLightACellContradictionRule/FullLightTest", lightUp); TreeNode rootNode = lightUp.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); - transition.setRule(RULE); + transition.setRule(RULE); LightUpBoard board = (LightUpBoard) transition.getBoard(); //confirm there is a contradiction somewhere on the board @@ -36,7 +36,7 @@ public void FullLightTest() throws InvalidFileFormatException { //confirm it is impossible to light up these squares Assert.assertNull(RULE.checkContradictionAt(board, board.getCell(1, 3))); Assert.assertNull(RULE.checkContradictionAt(board, board.getCell(3, 3))); - + //confirm these are not required to be lit because they are already lit or unable to be Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(0, 0))); Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(1, 1))); @@ -44,13 +44,13 @@ public void FullLightTest() throws InvalidFileFormatException { Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(3, 2))); } - @Test + @Test //simple contradiction testing for null and non-null in a 3x3 board public void CannotLightMiddleTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/lightup/rules/CannotLightACellContradictionRule/CannotLight", lightUp); TreeNode rootNode = lightUp.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); - transition.setRule(RULE); + transition.setRule(RULE); LightUpBoard board = (LightUpBoard) transition.getBoard(); //confirm there is a contradiction somewhere on the board @@ -68,4 +68,24 @@ public void CannotLightMiddleTest() throws InvalidFileFormatException { Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(1, 2))); Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(2, 1))); } + + @Test + public void CanLightTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/lightup/rules/CannotLightACellContradictionRule/CanLightTest", lightUp); + TreeNode rootNode = lightUp.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + LightUpBoard board = (LightUpBoard) transition.getBoard(); + //confirm there is not a contradiction somewhere on the board + Assert.assertNotNull(RULE.checkContradiction(board)); + + //confirm that these cells can be lit, are already lit, or that they are just black blocks + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(1, 3))); + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(3, 3))); + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkContradictionAt(board, board.getCell(3, 2))); + } } diff --git a/src/test/java/puzzles/lightup/rules/EmptyCellinLightDirectRuleTest.java b/src/test/java/puzzles/lightup/rules/EmptyCellinLightDirectRuleTest.java index 637804892..b0a2d10ed 100644 --- a/src/test/java/puzzles/lightup/rules/EmptyCellinLightDirectRuleTest.java +++ b/src/test/java/puzzles/lightup/rules/EmptyCellinLightDirectRuleTest.java @@ -59,16 +59,33 @@ public void EmptyCellinLightDirectRule() throws InvalidFileFormatException{ cell7.setData(LightUpCellType.EMPTY.value); board.addModifiedData(cell7); + LightUpCell cell8 = board.getCell(3,0); + cell8.setData(LightUpCellType.EMPTY.value); + board.addModifiedData(cell8); + + LightUpCell cell9 = board.getCell(3,2); + cell9.setData(LightUpCellType.EMPTY.value); + board.addModifiedData(cell9); + + LightUpCell cell10 = board.getCell(2,3); + cell10.setData(LightUpCellType.EMPTY.value); + board.addModifiedData(cell10); + + LightUpCell cell11 = board.getCell(0,3); + cell11.setData(LightUpCellType.EMPTY.value); + board.addModifiedData(cell11); + //confirm there is a logical following of the EmptyCellinLight rule Assert.assertNull(RULE.checkRule(transition)); - //cells (0,0) and (2,2) are not empty because they have lightbulbs, and (1,1) - //because it is a black tile. Confirm the rest are empty + //cells (0,0) and (2,2) are not empty because they have lightbulbs, (1,1) + //because it is a black tile, and (1,3),(3,1),(3,3) because they are not lit. Confirm the rest are empty LightUpCell c; for (int i = 0; i < board.getHeight(); i++) { for (int j = 0; j < board.getWidth(); j++) { c = board.getCell(j, i); - if ((i == 0 && j == 0) || (i == 2 && j == 2) || (i == 1 && j == 1)){ + if ((i == 0 && j == 0) || (i == 2 && j == 2) || (i == 1 && j == 1) || (i == 1 && j == 3) || (i == 3 && j == 1) + || (i==3 && j==3)){ Assert.assertNotNull(RULE.checkRuleAt(transition, c)); } else { diff --git a/src/test/java/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRuleTest.java b/src/test/java/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRuleTest.java index b32ce23ce..7e8b5eb83 100644 --- a/src/test/java/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRuleTest.java +++ b/src/test/java/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRuleTest.java @@ -30,6 +30,9 @@ public static void setUp() { nurikabe = new Nurikabe(); } + /** + * Tests the Black Between Regions direct rule for regions that are diagonal to each other (diagonal going from top left to bottom right) + */ @Test public void BlackBetweenRegionsDirectRule_DiagonalBlackBetweenRegions1Test() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/DiagonalBlackBetweenRegions1", nurikabe); @@ -62,6 +65,9 @@ public void BlackBetweenRegionsDirectRule_DiagonalBlackBetweenRegions1Test() thr } } + /** + * Tests the Black Between Regions direct rule for regions that are diagonal to each other (diagonal going from bottom left to top right) + */ @Test public void BlackBetweenRegionsDirectRule_DiagonalBlackBetweenRegions2Test() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/DiagonalBlackBetweenRegions2", nurikabe); @@ -94,6 +100,9 @@ public void BlackBetweenRegionsDirectRule_DiagonalBlackBetweenRegions2Test() thr } } + /** + * Tests the Black Between Regions direct rule for regions that are horizontally opposite each other + */ @Test public void BlackBetweenRegionsDirectRule_HorizontalBlackBetweenRegionsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/HorizontalBlackBetweenRegions", nurikabe); @@ -123,6 +132,9 @@ public void BlackBetweenRegionsDirectRule_HorizontalBlackBetweenRegionsTest() th } } + /** + * Tests the Black Between Regions direct rule for regions that are vertically opposite each other + */ @Test public void BlackBetweenRegionsDirectRule_VerticalBlackBetweenRegionsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/VerticalBlackBetweenRegions", nurikabe); @@ -151,4 +163,28 @@ public void BlackBetweenRegionsDirectRule_VerticalBlackBetweenRegionsTest() thro } } } + + /** + * Tests the Black Between Regions direct rule for a false application of the rule, where a black tile is enclosed by one region + */ + @Test + public void BlackBetweenRegionsDirectRule_FalseBlackBetweenRegionsTest() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/FalseBlackBetweenRegions",nurikabe); + TreeNode rootNode = nurikabe.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + NurikabeBoard board = (NurikabeBoard) transition.getBoard(); + NurikabeCell cell = board.getCell(1,1); + cell.setData(NurikabeType.BLACK.toValue()); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + + for(int i=0; i cases = RULE.getCases(board,cell); + + Assert.assertEquals(2,cases.size()); + + NurikabeBoard caseBoard = (NurikabeBoard) cases.get(0); + NurikabeBoard caseBoard2 = (NurikabeBoard) cases.get(1); + + NurikabeType board1Type = caseBoard.getCell(0,0).getType(); + NurikabeType board2Type = caseBoard2.getCell(0,0).getType(); + + Assert.assertTrue((board1Type.equals(NurikabeType.BLACK) || board1Type.equals(NurikabeType.WHITE)) && + (board2Type.equals(NurikabeType.BLACK) || board2Type.equals(NurikabeType.WHITE))); + Assert.assertFalse(board1Type.equals(board2Type)); + + Assert.assertEquals(caseBoard.getHeight(),caseBoard2.getHeight(), board.getHeight()); + Assert.assertEquals(caseBoard.getWidth(),caseBoard2.getWidth(), board.getWidth()); + + for(int i=0; i cases = RULE.getCases(board, cell); + + // Make sure that the rule checks out + Assert.assertNotNull(RULE.checkRule(transition)); + + // Make sure there are two branches + Assert.assertEquals(2, cases.size()); + + ShortTruthTableBoard caseBoard1 = (ShortTruthTableBoard) cases.get(0); + ShortTruthTableCellType board1A = caseBoard1.getCell(aX, aY).getType(); + ShortTruthTableCellType board1B = caseBoard1.getCell(bX, bY).getType(); + + ShortTruthTableBoard caseBoard2 = (ShortTruthTableBoard) cases.get(1); + ShortTruthTableCellType board2A = caseBoard2.getCell(aX, aY).getType(); + ShortTruthTableCellType board2B = caseBoard2.getCell(bX, bY).getType(); + + // Assert that the corresponding cells for the different case rules do not + // match with each other + Assert.assertNotEquals(board1A, board2A); + Assert.assertNotEquals(board1B, board2B); + + // First assert the two cells are not equal, then verify that they are either + // unknown or false. + Assert.assertNotEquals(board1A, board1B); + Assert.assertTrue(board1A.equals(ShortTruthTableCellType.UNKNOWN) || board1A.equals(ShortTruthTableCellType.FALSE)); + Assert.assertTrue(board1B.equals(ShortTruthTableCellType.UNKNOWN) || board1B.equals(ShortTruthTableCellType.FALSE)); + + Assert.assertNotEquals(board2A, board2B); + Assert.assertTrue(board2A.equals(ShortTruthTableCellType.UNKNOWN) || board1A.equals(ShortTruthTableCellType.FALSE)); + Assert.assertTrue(board2B.equals(ShortTruthTableCellType.UNKNOWN) || board2B.equals(ShortTruthTableCellType.FALSE)); + + // Verify the board dimensions are unchanged + Assert.assertEquals(caseBoard1.getHeight(), caseBoard2.getHeight(), board.getHeight()); + Assert.assertEquals(caseBoard1.getWidth(), caseBoard2.getWidth(), board.getWidth()); + + // Verify that everywhere else on the board is unchanged + for (int i = 0; i< caseBoard1.getWidth(); i++) { + for (int j = 0; j < caseBoard1.getHeight(); j++) { + // Make sure not to check the two cells that should be different + if (!((i == aX && j == aY) || (i == bX && j == bY))) { + Assert.assertEquals(caseBoard1.getCell(i, j).getType(), caseBoard2.getCell(i, j).getType()); + } + } + } + } + + /** + * Given a statement A ^ B where ^ is false, tests this case rule by ensuring that + * two branches are created: one where A is false and one where B is false. + */ + @Test + public void SimpleStatement1FalseTest() throws InvalidFileFormatException { + falseAndTest("SimpleStatement1_False", 1, 0, 0, 0, + 2, 0); + } + + /** + * Given a statement ~(A|B)^(C^D) where the first ^ is false, tests this case rule + * by ensuring that two branches are created: one where ~ is false and one where + * the second ^ is false. + */ + @Test + public void ComplexStatement1FalseTest() throws InvalidFileFormatException { + falseAndTest("ComplexStatement1_False", 6, 0, 0, 0, + 9, 0); + } + + private void trueAndTest(String fileName, + int andX, int andY, + int aX, int aY, + int bX, int bY) throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AndCaseRule/" + fileName, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell cell = board.getCell(andX,andY); + ArrayList cases = RULE.getCases(board, cell); + + // Make sure that the rule checks out + Assert.assertNotNull(RULE.checkRule(transition)); + + // There should only be 1 branch + Assert.assertEquals(1, cases.size()); + + ShortTruthTableBoard caseBoard = (ShortTruthTableBoard) cases.get(0); + ShortTruthTableCellType caseBoardAType = caseBoard.getCell(aX, aY).getType(); + ShortTruthTableCellType caseBoardBType = caseBoard.getCell(bX, bY).getType(); + + // Both cells should be true + Assert.assertEquals(caseBoardAType, ShortTruthTableCellType.TRUE); + Assert.assertEquals(caseBoardBType, ShortTruthTableCellType.TRUE); + Assert.assertEquals(caseBoardAType, caseBoardBType); + + // Verify the board dimensions are unchanged + Assert.assertEquals(caseBoard.getHeight(), caseBoard.getHeight(), board.getHeight()); + } + + /** + * Given a statement A ^ B where ^ is false, tests this case rule by ensuring that + * one branch is created where A and B are both true. + */ + @Test + public void SimpleStatement1AndTest() throws InvalidFileFormatException { + trueAndTest("SimpleStatement1_True", 1, 0, 0, 0, + 2, 0); + } + + /** + * Given a statement ~(A|B)^(C^D) where the first ^ is true, tests this case rule + * by ensuring that one branch is created where both ~ and the second ^ are true. + */ + @Test + public void ComplexStatement1TrueTest() throws InvalidFileFormatException { + trueAndTest("ComplexStatement1_True", 6, 0, 0, 0, + 9, 0); + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/AndEliminationDirectRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/AndEliminationDirectRuleTest.java new file mode 100644 index 000000000..0d94eb672 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/AndEliminationDirectRuleTest.java @@ -0,0 +1,204 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.elimination.DirectRuleAndElimination; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class AndEliminationDirectRuleTest { + private static final DirectRuleAndElimination RULE = new DirectRuleAndElimination(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given one statement: B^C where ^ is true + * + * Checks all possible combinations of true, false, and unknown for B and C + * except for where both B and C are true and asserts that each one of them + * is not a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void trueAndTest1() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AndEliminationDirectRule/TrueAnd", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + if (cellType1 == cellType2 && cellType1 == ShortTruthTableCellType.TRUE) { + continue; + } + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell bonnie = board.getCell(0, 0); + ShortTruthTableCell clyde = board.getCell(2, 0); + + if (cellType1 != ShortTruthTableCellType.UNKNOWN) { + bonnie.setData(cellType1); + board.addModifiedData(bonnie); + } + + if (cellType2 != ShortTruthTableCellType.UNKNOWN) { + clyde.setData(cellType2); + board.addModifiedData(clyde); + } + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: B^C where ^ is true + * + * Checks all possible combinations of true and unknown for B and C + * except for where both B and C are unknown and asserts that each one + * of them is a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void trueAndTest2() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AndEliminationDirectRule/TrueAnd", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + if (cellType1 == cellType2 && cellType1 == ShortTruthTableCellType.UNKNOWN) { + continue; + } + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell bonnie = board.getCell(0, 0); + ShortTruthTableCell clyde = board.getCell(2, 0); + + if (cellType1 != ShortTruthTableCellType.UNKNOWN) { + bonnie.setData(cellType1); + board.addModifiedData(bonnie); + } + + if (cellType2 != ShortTruthTableCellType.UNKNOWN) { + clyde.setData(cellType2); + board.addModifiedData(clyde); + } + + Assert.assertNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: B^C where ^ is false + * + * Checks all possible combinations of true, false, and unknown for B and C + * and asserts that each one of them is not a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void falseAndWithUnknownsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAnd", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell bonnie = board.getCell(0, 0); + ShortTruthTableCell clyde = board.getCell(2, 0); + + if (cellType1 != ShortTruthTableCellType.UNKNOWN) { + bonnie.setData(cellType1); + board.addModifiedData(bonnie); + } + + if (cellType2 != ShortTruthTableCellType.UNKNOWN) { + clyde.setData(cellType2); + board.addModifiedData(clyde); + } + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: B^C where both B and ^ are false + * + * Asserts that this is not a valid application of the rule if C is set to + * either true or false. + * + * @throws InvalidFileFormatException + */ + @Test + public void falseAndWithKnownFalseTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownFalse", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell clyde = board.getCell(2, 0); + clyde.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(clyde); + Assert.assertNotNull(RULE.checkRule(transition)); + + clyde.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(clyde); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: B^C where B is true and ^ is false + * + * Asserts that this is a valid application of the rule if and only if C is + * set to false. + * + * @throws InvalidFileFormatException + */ + @Test + public void falseAndWithKnownTrueTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownTrue", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell clyde = board.getCell(2, 0); + clyde.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(clyde); + Assert.assertNotNull(RULE.checkRule(transition)); + + clyde.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(clyde); + Assert.assertNull(RULE.checkRule(transition)); + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/AndIntroductionDirectRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/AndIntroductionDirectRuleTest.java new file mode 100644 index 000000000..4d4e009b2 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/AndIntroductionDirectRuleTest.java @@ -0,0 +1,105 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.introduction.DirectRuleAndIntroduction; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class AndIntroductionDirectRuleTest { + private static final DirectRuleAndIntroduction RULE = new DirectRuleAndIntroduction(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given a statement: A ^ B + * + * Asserts that if at least 1 of A or B is false, then this is a valid application + * of the rule if and only if ^ is false. + * + * @param filePath The file path for test board setup. + * @throws InvalidFileFormatException + */ + @Test + public void FalseAndTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/AndIntroductionDirectRule/"; + falseAndTestHelper(path + "FUF"); + falseAndTestHelper(path + "FUU"); + falseAndTestHelper(path + "UUF"); + falseAndTestHelper(path + "FUT"); + falseAndTestHelper(path + "TUF"); + } + + private void falseAndTestHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell and = board.getCell(1, 0); + + and.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(and); + Assert.assertNotNull(RULE.checkRule(transition)); + + and.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(and); + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given a statement: A ^ B + * + * Asserts that setting ^ to true is a valid application of the rule if + * and only if both A and B are true. + * + * @param filePath The file path for test board setup. + * @throws InvalidFileFormatException + */ + @Test + public void FalseOrTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/AndIntroductionDirectRule/"; + String[] letters = {"T", "F", "U"}; + for (String first : letters) { + for (String second : letters) { + trueAndTestHelper(path + first + "U" + second); + } + } + } + + private void trueAndTestHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + ShortTruthTableCell and = board.getCell(1, 0); + + and.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(and); + + if (a.getType() == ShortTruthTableCellType.TRUE && b.getType() == ShortTruthTableCellType.TRUE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/AtomicDirectRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/AtomicDirectRuleTest.java new file mode 100644 index 000000000..51aa213c6 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/AtomicDirectRuleTest.java @@ -0,0 +1,188 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.DirectRuleAtomic; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class AtomicDirectRuleTest { + private static final DirectRuleAtomic RULE = new DirectRuleAtomic(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given two statements: + * A + * A + * where the first A is set to false. + * + * This test sets the second A to false and then asserts that this + * is a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void MatchingFalseTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AtomicDirectRule/FalseA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell cell = board.getCell(0, 2); + cell.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(cell); + + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given two statements: + * A + * A + * where the first A is set to false. + * + * This test sets the second A to true and then asserts that this + * is not a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void MismatchingFalseTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AtomicDirectRule/FalseA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell cell = board.getCell(0, 2); + cell.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given two statements: + * B + * B + * where the first B is set to true. + * + * This test sets the second B to true and then asserts that this + * is a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void MatchingTrueTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AtomicDirectRule/TrueB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell cell = board.getCell(0, 2); + cell.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(cell); + + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given two statements: + * B + * B + * where the first B is set to true. + * + * This test sets the second B to false and then asserts that this + * is not a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void MismatchingTrueTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AtomicDirectRule/TrueB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell cell = board.getCell(0, 2); + cell.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given two statements: + * C + * C + * where neither statement is set to anything. + * + * This test sets the second C to false and then asserts that this + * is not a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void NothingPreviouslyMarkedTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AtomicDirectRule/Empty", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell cell = board.getCell(0, 2); + cell.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given two statements: + * C + * C + * where neither statement is set to anything. + * + * This test sets the second C to true and then asserts that this + * is not a valid application of the rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void NothingPreviouslyMarkedTest2() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/AtomicDirectRule/Empty", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + + ShortTruthTableCell cell = board.getCell(0, 2); + cell.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/BiconditionalEliminationTest.java b/src/test/java/puzzles/shorttruthtable/rules/BiconditionalEliminationTest.java new file mode 100644 index 000000000..05faf87bb --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/BiconditionalEliminationTest.java @@ -0,0 +1,373 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.elimination.DirectRuleBiconditionalElimination; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BiconditionalEliminationTest { + private static final DirectRuleBiconditionalElimination RULE = new DirectRuleBiconditionalElimination(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given one statement: A <-> B where both A and <-> are true + * + * Asserts that this is a valid application of the rule if and only if B is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueBiconditionalWithTrueATest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell morty = board.getCell(2, 0); + + // Asserts that this is not a valid application of the rule when B is unknown + morty.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when B is true + morty.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(morty); + Assert.assertNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when B is false + morty.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where both B and <-> are true + * + * Asserts that this is a valid application of the rule if and only if A is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueBiconditionalWithTrueBTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell rick = board.getCell(0, 0); + + // Asserts that this is a valid application of the rule when A is true + rick.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(rick); + Assert.assertNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when A is unknown + rick.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when A is false + rick.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + + /** + * Given one statement: A <-> B where A is false and <-> is true + * + * Asserts that this is a valid application of the rule if and only if B is false. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueBiconditionalWithFalseATest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell morty = board.getCell(2, 0); + + // Asserts that this is not a valid application of the rule when B is unknown + morty.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when B is true + morty.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when B is false + morty.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(morty); + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where B is false and <-> is true + * + * Asserts that this is a valid application of the rule if and only if A is false. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueBiconditionalWithFalseBTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell rick = board.getCell(0, 0); + + // Asserts that this is not a valid application of the rule when A is unknown + rick.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when A is true + rick.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when A is false + rick.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(rick); + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where A is true and <-> is false + * + * Asserts that this is a valid application of the rule if and only if B is false. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseBiconditionalWithTrueATest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell morty = board.getCell(2, 0); + + // Asserts that this is not a valid application of the rule when B is unknown + morty.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when B is true + morty.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when B is false + morty.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(morty); + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where B is true and <-> is false + * + * Asserts that this is a valid application of the rule if and only if A is false. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseBiconditionalWithTrueBTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell rick = board.getCell(0, 0); + + // Asserts that this is not a valid application of the rule when A is unknown + rick.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when A is true + rick.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when A is false + rick.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(rick); + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where A and <-> are false + * + * Asserts that this is a valid application of the rule if and only if B is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseBiconditionalWithFalseATest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell morty = board.getCell(2, 0); + + // Asserts that this is not a valid application of the rule when B is unknown + morty.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when B is true + morty.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(morty); + Assert.assertNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when B is false + morty.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(morty); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where B and <-> are false + * + * Asserts that this is a valid application of the rule if and only if A is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseBiconditionalWithFalseBTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell rick = board.getCell(0, 0); + + // Asserts that this is not a valid application of the rule when A is unknown + rick.setData(ShortTruthTableCellType.UNKNOWN); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is not a valid application of the rule when A is false + rick.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(rick); + Assert.assertNotNull(RULE.checkRule(transition)); + + // Asserts that this is a valid application of the rule when A is true + rick.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(rick); + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A <-> B where <-> is true + * + * Asserts that setting any combination of A and B at the same time is not a valid + * application of this rule + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueBiconditionalSetBothAtOnceTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditional", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell rick = board.getCell(0, 0); + ShortTruthTableCell morty = board.getCell(2, 0); + + rick.setData(cellType1); + morty.setData(cellType2); + + board.addModifiedData(rick); + board.addModifiedData(morty); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Asserts that setting any combination of A and B at the same time is not a valid + * application of this rule. This is tested on multiple files. + * + * @throws InvalidFileFormatException + */ + @Test + public void CannotSetBothAandBAtOnceTest() throws InvalidFileFormatException { + String directory = "puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/"; + setAandBBothAtOnceTest(directory + "FalseBiconditional"); + setAandBBothAtOnceTest(directory + "TrueBiconditional"); + setAandBBothAtOnceTest(directory + "FalseBiconditionalWithFalseA"); + setAandBBothAtOnceTest(directory + "TrueBiconditionalWithFalseA"); + setAandBBothAtOnceTest(directory + "FalseBiconditionalWithTrueA"); + setAandBBothAtOnceTest(directory + "TrueBiconditionalWithTrueA"); + } + + /** + * Helper function to test biconditional elimination rule with given file path. + * + * @param filePath The file path for test board setup. + * @throws InvalidFileFormatException + */ + private void setAandBBothAtOnceTest(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell rick = board.getCell(0, 0); + ShortTruthTableCell morty = board.getCell(2, 0); + + rick.setData(cellType1); + morty.setData(cellType2); + + board.addModifiedData(rick); + board.addModifiedData(morty); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/BiconditionalIntroductionTest.java b/src/test/java/puzzles/shorttruthtable/rules/BiconditionalIntroductionTest.java new file mode 100644 index 000000000..fe2574b5e --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/BiconditionalIntroductionTest.java @@ -0,0 +1,118 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.introduction.DirectRuleBiconditionalIntroduction; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class BiconditionalIntroductionTest { + private static final DirectRuleBiconditionalIntroduction RULE = new DirectRuleBiconditionalIntroduction(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given a statement: A <-> B + * + * Asserts that if setting <-> to false is a valid application of this rule if and + * only if A and B do not match. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseConditionalTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/"; + + String[] letters = {"T", "F", "U"}; + for (String a : letters) { + for (String b : letters) { + System.out.println(a + b); + falseConditionalHelper(path + a + "U" + b); + } + } + } + + private void falseConditionalHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell conditional = board.getCell(1, 0); + + conditional.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(conditional); + + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + if (a.getType() != b.getType()) { + // Not valid if they don't match but at least one of the values of A or B is unknown + if (a.getType() == ShortTruthTableCellType.UNKNOWN || b.getType() == ShortTruthTableCellType.UNKNOWN) { + Assert.assertNotNull(RULE.checkRule(transition)); + } + else { + Assert.assertNull(RULE.checkRule(transition)); + } + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + + /** + * Given a statement: A <-> B + * + * Asserts that if setting <-> to true is a valid application of this rule if and + * only if A and B match. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueConditionalTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/"; + + String[] letters = {"T", "F", "U"}; + for (String a : letters) { + for (String b : letters) { + System.out.println(a + b); + trueConditionalHelper(path + a + "U" + b); + } + } + } + + private void trueConditionalHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell conditional = board.getCell(1, 0); + + conditional.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(conditional); + + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + if (a.getType() == b.getType() && a.getType() != ShortTruthTableCellType.UNKNOWN) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/ConditionalEliminationTest.java b/src/test/java/puzzles/shorttruthtable/rules/ConditionalEliminationTest.java new file mode 100644 index 000000000..8d0bb4e1a --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/ConditionalEliminationTest.java @@ -0,0 +1,233 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.elimination.DirectRuleConditionalElimination; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ConditionalEliminationTest { + private static final DirectRuleConditionalElimination RULE = new DirectRuleConditionalElimination(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given one statement: A -> B where -> is false + * + * Asserts that the only valid combination of A and B that is a valid application + * of this rule is when A is true and B is false + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseConditionalTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/FalseConditional", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell aubergine = board.getCell(0, 0); + ShortTruthTableCell boniato = board.getCell(2, 0); + + aubergine.setData(cellType1); + boniato.setData(cellType2); + + board.addModifiedData(aubergine); + board.addModifiedData(boniato); + + if (cellType1 == ShortTruthTableCellType.TRUE && cellType2 == ShortTruthTableCellType.FALSE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + } + + /** + * Given one statement: A -> B where -> is false + * + * Asserts that this is a valid application of the rule if and only if A + * is set to true. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseConditionalTrueATest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/FalseConditional", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell aubergine = board.getCell(0, 0); + + aubergine.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(aubergine); + Assert.assertNull(RULE.checkRule(transition)); + + aubergine.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(aubergine); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A -> B where -> is false + * + * Asserts that this is a valid application of the rule if and only if B is + * set to false. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseConditionalFalseBTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/FalseConditional", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell boniato = board.getCell(2, 0); + + boniato.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(boniato); + Assert.assertNull(RULE.checkRule(transition)); + + boniato.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(boniato); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A -> B where -> is true + * + * Asserts that you cannot set any combination of both A and B at the same time. + * + * @throws InvalidFileFormatException + */ + @Test + public void CannotSetBothAandBTrueConditionalTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditional", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell aubergine = board.getCell(0, 0); + ShortTruthTableCell boniato = board.getCell(2, 0); + + aubergine.setData(cellType1); + boniato.setData(cellType2); + + board.addModifiedData(aubergine); + board.addModifiedData(boniato); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: A -> B where A and -> are true + * + * Asserts that this is a valid application of this rule if and only if B + * is set to true. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueAMeansTrueBTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell boniato = board.getCell(2, 0); + + boniato.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(boniato); + Assert.assertNull(RULE.checkRule(transition)); + + boniato.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(boniato); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A -> B where B is false and -> is true + * + * Asserts that this is a valid application of this rule if and only if A + * is set to false. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseBMeansFalseATest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithFalseB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell aubergine = board.getCell(0, 0); + + aubergine.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(aubergine); + Assert.assertNull(RULE.checkRule(transition)); + + aubergine.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(aubergine); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given one statement: A -> B where B and -> are true + * + * Asserts that this is not a valid application of this rule no matter what + * A is set to. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueBCannotDetermineA() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueB", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell boniato = board.getCell(2, 0); + + boniato.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(boniato); + Assert.assertNotNull(RULE.checkRule(transition)); + + boniato.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(boniato); + Assert.assertNotNull(RULE.checkRule(transition)); + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/ConditionalIntroductionTest.java b/src/test/java/puzzles/shorttruthtable/rules/ConditionalIntroductionTest.java new file mode 100644 index 000000000..c1507eab1 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/ConditionalIntroductionTest.java @@ -0,0 +1,110 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.introduction.DirectRuleConditionalIntroduction; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ConditionalIntroductionTest { + private static final DirectRuleConditionalIntroduction RULE = new DirectRuleConditionalIntroduction(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given a statement: A -> B + * + * Asserts that if setting -> to false is a valid application of this rule if and + * only if A is true and B is false. + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseConditionalTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/"; + + String[] letters = {"T", "F", "U"}; + for (String a : letters) { + for (String b : letters) { + falseConditionalHelper(path + a + "U" + b); + } + } + } + + private void falseConditionalHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell conditional = board.getCell(1, 0); + + conditional.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(conditional); + + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + if (a.getType() == ShortTruthTableCellType.TRUE && b.getType() == ShortTruthTableCellType.FALSE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + + /** + * Given a statement: A -> B + * + * Asserts that if setting -> to true is a valid application of this rule if and + * only if A is false or B is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueConditionalTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/"; + + String[] letters = {"T", "F", "U"}; + for (String a : letters) { + for (String b : letters) { + trueConditionalTestHelper(path + a + "U" + b); + } + } + } + + private void trueConditionalTestHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell conditional = board.getCell(1, 0); + + conditional.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(conditional); + + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + if (a.getType() == ShortTruthTableCellType.FALSE || b.getType() == ShortTruthTableCellType.TRUE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/DirectRuleAtomicTest.java b/src/test/java/puzzles/shorttruthtable/rules/DirectRuleAtomicTest.java deleted file mode 100644 index 81991fa46..000000000 --- a/src/test/java/puzzles/shorttruthtable/rules/DirectRuleAtomicTest.java +++ /dev/null @@ -1,6 +0,0 @@ -package puzzles.shorttruthtable.rules; - -class DirectRuleAtomicTest { - - -} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/NotEliminationTest.java b/src/test/java/puzzles/shorttruthtable/rules/NotEliminationTest.java new file mode 100644 index 000000000..6dbbf141c --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/NotEliminationTest.java @@ -0,0 +1,124 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.elimination.DirectRuleNotElimination; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class NotEliminationTest { + private static final DirectRuleNotElimination RULE = new DirectRuleNotElimination(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given one statement: ¬A where ¬ is false + * + * Asserts that this is a valid application of this rule if and only if A is true + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseNot() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/NotEliminationDirectRule/FalseNot", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell a = board.getCell(1, 0); + a.setData(cellType); + board.addModifiedData(a); + + if (cellType == ShortTruthTableCellType.TRUE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: ¬A where ¬ is true + * + * Asserts that this is a valid application of this rule if and only if A is false + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueNot() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/NotEliminationDirectRule/TrueNot", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell a = board.getCell(1, 0); + a.setData(cellType); + board.addModifiedData(a); + + if (cellType == ShortTruthTableCellType.FALSE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + +// /** +// * Given one statement: ¬A +// * +// * Asserts that setting both ¬ and A to any values would not be a valid +// * application of this rule +// * +// * @throws InvalidFileFormatException +// */ +// @Test +// public void CannotSetBothAtOnceTest() throws InvalidFileFormatException { +// TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/NotEliminationDirectRule/BlankNot", stt); +// TreeNode rootNode = stt.getTree().getRootNode(); +// TreeTransition transition = rootNode.getChildren().get(0); +// transition.setRule(RULE); +// +// ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; +// +// for (ShortTruthTableCellType cellType1 : cellTypes) { +// for (ShortTruthTableCellType cellType2 : cellTypes) { +// ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); +// ShortTruthTableCell not = board.getCell(0, 0); +// ShortTruthTableCell a = board.getCell(1, 0); +// +// not.setData(cellType1); +// a.setData(cellType2); +// +// board.addModifiedData(not); +// board.addModifiedData(a); +// +// System.out.println("TYPE1:" + cellType1); +// System.out.println("TYPE2:" + cellType2); +// Assert.assertNotNull(RULE.checkRule(transition)); +// } +// } +// } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/NotIntroductionTest.java b/src/test/java/puzzles/shorttruthtable/rules/NotIntroductionTest.java new file mode 100644 index 000000000..a0a062ab3 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/NotIntroductionTest.java @@ -0,0 +1,122 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.introduction.DirectRuleNotIntroduction; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class NotIntroductionTest { + private static final DirectRuleNotIntroduction RULE = new DirectRuleNotIntroduction(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given one statement: ¬A where A is false + * + * Asserts that this is a valid application of this rule if and only if ¬ is true + * + * @throws InvalidFileFormatException + */ + @Test + public void FalseNot() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/NotIntroductionDirectRule/FalseA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell not = board.getCell(0, 0); + not.setData(cellType); + board.addModifiedData(not); + + if (cellType == ShortTruthTableCellType.TRUE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: ¬A where A is true + * + * Asserts that this is a valid application of this rule if and only if ¬ is false + * + * @throws InvalidFileFormatException + */ + @Test + public void TrueNot() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/NotIntroductionDirectRule/TrueA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell not = board.getCell(0, 0); + not.setData(cellType); + board.addModifiedData(not); + + if (cellType == ShortTruthTableCellType.FALSE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + + /** + * Given one statement: ¬A + * + * Asserts that setting both ¬ and A to any values would not be a valid + * application of this rule + * + * @throws InvalidFileFormatException + */ + @Test + public void CannotSetBothAtOnceTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/NotIntroductionDirectRule/BlankA", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell not = board.getCell(0, 0); + ShortTruthTableCell a = board.getCell(1, 0); + + not.setData(cellType1); + a.setData(cellType2); + + board.addModifiedData(not); + board.addModifiedData(a); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java new file mode 100644 index 000000000..276e822cf --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java @@ -0,0 +1,161 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.caserule.CaseRuleAnd; +import edu.rpi.legup.puzzle.shorttruthtable.rules.caserule.CaseRuleOr; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; + +public class OrCaseRuleTest { + + private static final CaseRuleOr RULE = new CaseRuleOr(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + private void trueOrTest(String fileName, + int andX, int andY, + int aX, int aY, + int bX, int bY) throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/OrCaseRule/" + fileName, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell cell = board.getCell(andX,andY); + ArrayList cases = RULE.getCases(board, cell); + + // Make sure that the rule checks out + Assert.assertNotNull(RULE.checkRule(transition)); + + // Make sure there are two branches + Assert.assertEquals(2, cases.size()); + + ShortTruthTableBoard caseBoard1 = (ShortTruthTableBoard) cases.get(0); + ShortTruthTableCellType board1A = caseBoard1.getCell(aX, aY).getType(); + ShortTruthTableCellType board1B = caseBoard1.getCell(bX, bY).getType(); + + ShortTruthTableBoard caseBoard2 = (ShortTruthTableBoard) cases.get(1); + ShortTruthTableCellType board2A = caseBoard2.getCell(aX, aY).getType(); + ShortTruthTableCellType board2B = caseBoard2.getCell(bX, bY).getType(); + + // Assert that the corresponding cells for the different case rules do not + // match with each other + Assert.assertNotEquals(board1A, board2A); + Assert.assertNotEquals(board1B, board2B); + + // First assert the two cells are not equal, then verify that they are either + // unknown or false. + Assert.assertNotEquals(board1A, board1B); + Assert.assertTrue(board1A.equals(ShortTruthTableCellType.UNKNOWN) || board1A.equals(ShortTruthTableCellType.TRUE)); + Assert.assertTrue(board1B.equals(ShortTruthTableCellType.UNKNOWN) || board1B.equals(ShortTruthTableCellType.TRUE)); + + Assert.assertNotEquals(board2A, board2B); + Assert.assertTrue(board2A.equals(ShortTruthTableCellType.UNKNOWN) || board1A.equals(ShortTruthTableCellType.TRUE)); + Assert.assertTrue(board2B.equals(ShortTruthTableCellType.UNKNOWN) || board2B.equals(ShortTruthTableCellType.TRUE)); + + // Verify the board dimensions are unchanged + Assert.assertEquals(caseBoard1.getHeight(), caseBoard2.getHeight(), board.getHeight()); + Assert.assertEquals(caseBoard1.getWidth(), caseBoard2.getWidth(), board.getWidth()); + + // Verify that everywhere else on the board is unchanged + for (int i = 0; i< caseBoard1.getWidth(); i++) { + for (int j = 0; j < caseBoard1.getHeight(); j++) { + // Make sure not to check the two cells that should be different + if (!((i == aX && j == aY) || (i == bX && j == bY))) { + Assert.assertEquals(caseBoard1.getCell(i, j).getType(), caseBoard2.getCell(i, j).getType()); + } + } + } + } + + /** + * Given a statement A ^ B where ^ is false, tests this case rule by ensuring that + * two branches are created: one where A is false and one where B is false. + */ + @Test + public void SimpleStatement1TrueTest() throws InvalidFileFormatException { + trueOrTest("SimpleStatement1_True", 1, 0, 0, 0, + 2, 0); + } + + /** + * Given a statement ~(A|B)^(C^D) where the first ^ is false, tests this case rule + * by ensuring that two branches are created: one where ~ is false and one where + * the second ^ is false. + */ + @Test + public void ComplexStatement1TrueTest() throws InvalidFileFormatException { + trueOrTest("ComplexStatement1_True", 6, 0, 0, 0, + 9, 0); + } + + private void falseOrTest(String fileName, + int andX, int andY, + int aX, int aY, + int bX, int bY) throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/OrCaseRule/" + fileName, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell cell = board.getCell(andX,andY); + ArrayList cases = RULE.getCases(board, cell); + + // Make sure that the rule checks out + Assert.assertNotNull(RULE.checkRule(transition)); + + // There should only be 1 branch + Assert.assertEquals(1, cases.size()); + + ShortTruthTableBoard caseBoard = (ShortTruthTableBoard) cases.get(0); + ShortTruthTableCellType caseBoardAType = caseBoard.getCell(aX, aY).getType(); + ShortTruthTableCellType caseBoardBType = caseBoard.getCell(bX, bY).getType(); + + // Both cells should be true + Assert.assertEquals(caseBoardAType, ShortTruthTableCellType.FALSE); + Assert.assertEquals(caseBoardBType, ShortTruthTableCellType.FALSE); + Assert.assertEquals(caseBoardAType, caseBoardBType); + + // Verify the board dimensions are unchanged + Assert.assertEquals(caseBoard.getHeight(), caseBoard.getHeight(), board.getHeight()); + } + + /** + * Given a statement A ^ B where ^ is false, tests this case rule by ensuring that + * one branch is created where A and B are both true. + */ + @Test + public void SimpleStatement1FalseTest() throws InvalidFileFormatException { + falseOrTest("SimpleStatement1_False", 1, 0, 0, 0, + 2, 0); + } + + /** + * Given a statement ~(A|B)^(C^D) where the first ^ is true, tests this case rule + * by ensuring that one branch is created where both ~ and the second ^ are true. + */ + @Test + public void ComplexStatement1FalseTest() throws InvalidFileFormatException { + falseOrTest("ComplexStatement1_False", 6, 0, 0, 0, + 9, 0); + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/OrEliminationTest.java b/src/test/java/puzzles/shorttruthtable/rules/OrEliminationTest.java new file mode 100644 index 000000000..6cdd0d639 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/OrEliminationTest.java @@ -0,0 +1,150 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.elimination.DirectRuleOrElimination; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class OrEliminationTest { + private static final DirectRuleOrElimination RULE = new DirectRuleOrElimination(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given a statement: A V B, where A is false and V is true + * + * Asserts that this is a valid application of the rule if and only if B is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void FTUTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/OrEliminationDirectRule/FTU", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell cell = board.getCell(2, 0); + + cell.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(cell); + Assert.assertNull(RULE.checkRule(transition)); + + cell.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(cell); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given a statement: A V B, where B is false and V is true + * + * Asserts that this is a valid application of the rule if and only if B is true. + * + * @throws InvalidFileFormatException + */ + @Test + public void UTFTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTF", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell cell = board.getCell(0, 0); + + cell.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(cell); + Assert.assertNull(RULE.checkRule(transition)); + + cell.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(cell); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given a statement: A V B, where V is false + * + * Asserts that this is a valid application of the rule if and only if both A + * and B are false. + * + * @throws InvalidFileFormatException + */ + @Test + public void UFUTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/OrEliminationDirectRule/UFU", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + + a.setData(cellType1); + b.setData(cellType2); + + board.addModifiedData(a); + board.addModifiedData(b); + + if (cellType1 == ShortTruthTableCellType.FALSE && cellType2 == ShortTruthTableCellType.FALSE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } + } + + /** + * Given a statement: A V B, where V is true + * + * Asserts that setting both A and B is not a valid application of this rule. + * + * @throws InvalidFileFormatException + */ + @Test + public void UTUTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTU", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableCellType[] cellTypes = {ShortTruthTableCellType.TRUE, ShortTruthTableCellType.FALSE, ShortTruthTableCellType.UNKNOWN}; + + for (ShortTruthTableCellType cellType1 : cellTypes) { + for (ShortTruthTableCellType cellType2 : cellTypes) { + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + + a.setData(cellType1); + b.setData(cellType2); + + board.addModifiedData(a); + board.addModifiedData(b); + + Assert.assertNotNull(RULE.checkRule(transition)); + } + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/OrIntroductionTest.java b/src/test/java/puzzles/shorttruthtable/rules/OrIntroductionTest.java new file mode 100644 index 000000000..13cb10d55 --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/OrIntroductionTest.java @@ -0,0 +1,105 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.basic.introduction.DirectRuleOrIntroduction; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class OrIntroductionTest { + private static final DirectRuleOrIntroduction RULE = new DirectRuleOrIntroduction(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setup() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Given a statement: A V B + * + * Asserts that if at least 1 of A or B is true, then this is a valid application + * of the rule if and only if V is true. + * + * @param filePath The file path for test board setup. + * @throws InvalidFileFormatException + */ + @Test + public void TrueOrTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/OrIntroductionDirectRule/"; + trueOrTestHelper(path + "TUT"); + trueOrTestHelper(path + "TUU"); + trueOrTestHelper(path + "UUT"); + trueOrTestHelper(path + "TUF"); + trueOrTestHelper(path + "FUT"); + } + + private void trueOrTestHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell or = board.getCell(1, 0); + + or.setData(ShortTruthTableCellType.TRUE); + board.addModifiedData(or); + Assert.assertNull(RULE.checkRule(transition)); + + or.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(or); + Assert.assertNotNull(RULE.checkRule(transition)); + } + + /** + * Given a statement: A V B + * + * Asserts that setting V to false is a valid application of the rule if + * and only if both A and B are false. + * + * @param filePath The file path for test board setup. + * @throws InvalidFileFormatException + */ + @Test + public void FalseOrTest() throws InvalidFileFormatException { + String path = "puzzles/shorttruthtable/rules/OrIntroductionDirectRule/"; + String[] letters = {"T", "F", "U"}; + for (String first : letters) { + for (String second : letters) { + falseOrTestHelper(path + first + "U" + second); + } + } + } + + private void falseOrTestHelper(String filePath) throws InvalidFileFormatException { + TestUtilities.importTestBoard(filePath, stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell a = board.getCell(0, 0); + ShortTruthTableCell b = board.getCell(2, 0); + ShortTruthTableCell or = board.getCell(1, 0); + + or.setData(ShortTruthTableCellType.FALSE); + board.addModifiedData(or); + + if (a.getType() == ShortTruthTableCellType.FALSE && b.getType() == ShortTruthTableCellType.FALSE) { + Assert.assertNull(RULE.checkRule(transition)); + } + else { + Assert.assertNotNull(RULE.checkRule(transition)); + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java new file mode 100644 index 000000000..849e9f15c --- /dev/null +++ b/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java @@ -0,0 +1,78 @@ +package puzzles.shorttruthtable.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTable; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.rules.caserule.CaseRuleAtomic; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; + +public class TrueOrFalseCaseRuleTest { + + private static final CaseRuleAtomic RULE = new CaseRuleAtomic(); + private static ShortTruthTable stt; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + stt = new ShortTruthTable(); + } + + /** + * Tests the True or False case rule by ensuring that it results in two children, + * one that contains Statement as true and one that contains Statement as false. + */ + @Test + public void TwoBranchesTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/shorttruthtable/rules/TrueOrFalseCaseRule/Statement", stt); + TreeNode rootNode = stt.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + ShortTruthTableBoard board = (ShortTruthTableBoard) transition.getBoard(); + ShortTruthTableCell cell = board.getCell(0,0); + ArrayList cases = RULE.getCases(board, cell); + + // Make sure that the rule checks out + Assert.assertNotNull(RULE.checkRule(transition)); + + // Make sure there are two branches + Assert.assertEquals(2, cases.size()); + + ShortTruthTableBoard caseBoard1 = (ShortTruthTableBoard) cases.get(0); + ShortTruthTableBoard caseBoard2 = (ShortTruthTableBoard) cases.get(1); + + ShortTruthTableCellType cellType1 = caseBoard1.getCell(0,0).getType(); + ShortTruthTableCellType cellType2 = caseBoard2.getCell(0,0).getType(); + + // First assert the two cells are not equal, then verify that they are true + // or false. + Assert.assertNotEquals(cellType1, cellType2); + Assert.assertTrue(cellType1.equals(ShortTruthTableCellType.TRUE) || cellType1.equals(ShortTruthTableCellType.FALSE)); + Assert.assertTrue(cellType2.equals(ShortTruthTableCellType.TRUE) || cellType2.equals(ShortTruthTableCellType.FALSE)); + + // Verify the board dimensions are unchanged + Assert.assertEquals(caseBoard1.getHeight(), caseBoard2.getHeight(), board.getHeight()); + Assert.assertEquals(caseBoard1.getWidth(), caseBoard2.getWidth(), board.getWidth()); + + // Verify that everywhere else on the board is unchanged + for (int i = 0; i< caseBoard1.getWidth(); i++) { + for (int j = 0; j < caseBoard1.getHeight(); j++) { + // Make sure not to check the one cell that should be different + if (i != 0 && j != 0) { + Assert.assertEquals(caseBoard1.getCell(i, j).getType(), caseBoard2.getCell(i, j).getType()); + } + } + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java index 50e2bb970..b7ec8eb02 100644 --- a/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java @@ -27,6 +27,9 @@ public static void setUp() { treetent = new TreeTent(); } + // creates a 3x3 puzzle with no trees + // make the (1,1) tile GRASS + // checks if tiles logically follow the EmptyFieldDirectRule @Test public void EmptyFieldTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/EmptyField", treetent); @@ -34,28 +37,38 @@ public void EmptyFieldTest() throws InvalidFileFormatException { TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); + // get board state TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + // change the board's cells considering the EmptyField rule TreeTentCell cell1 = board.getCell(1, 1); cell1.setData(TreeTentType.GRASS); - board.addModifiedData(cell1); + // confirm there is a logical following of the EmptyField rule Assert.assertNull(RULE.checkRule(transition)); + // only the cell above should change following the rule + TreeTentCell c; for (int i = 0; i < board.getHeight(); i++) { for (int k = 0; k < board.getWidth(); k++) { - Point point = new Point(k, i); - if (point.equals(cell1.getLocation())) { - Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); } else { - Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); } } } } + // creates a 3x3 puzzle with 4 trees + // trees are at (0,0), (2,0), (0,2), and (2,2) + // make the (1,1) tile GRASS. + // checks if tiles logically follow the EmptyFieldDirectRule @Test public void DiagonalTreeTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/DiagonalTree", treetent); @@ -63,26 +76,197 @@ public void DiagonalTreeTest() throws InvalidFileFormatException { TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); + // get board state TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + //change the board's cells considering the EmptyField rule TreeTentCell cell1 = board.getCell(1, 1); cell1.setData(TreeTentType.GRASS); - board.addModifiedData(cell1); + // confirm there is a logical following of the EmptyField rule Assert.assertNull(RULE.checkRule(transition)); + // only the cell above should change following the rule + TreeTentCell c; for (int i = 0; i < board.getHeight(); i++) { for (int k = 0; k < board.getWidth(); k++) { - Point point = new Point(k, i); - if (point.equals(cell1.getLocation())) { - Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); } else { - Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); } } } } + + // creates a 3x3 puzzle with 4 trees + // trees are at (0,1), (1,0), (1,2), and (2,1) + // make the (1,1) tile GRASS. + // checks if tiles don't logically follow the EmptyFieldDirectRule + @Test + public void EmptyFieldTestFail() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFail", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + //change the board's cells considering breaking the EmptyField rule + TreeTentCell cell1 = board.getCell(1, 1); + cell1.setData(TreeTentType.GRASS); + board.addModifiedData(cell1); + + // confirm there is not a logical following of the EmptyField rule + Assert.assertNotNull(RULE.checkRule(transition)); + + // the cells should not follow the rule + TreeTentCell c; + for (int i = 0; i < board.getWidth(); i++) { + for (int j = 0; j < board.getHeight(); j++) { + c = board.getCell(j, i); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + + // creates a 3x3 puzzle with 1 tree + // tree is at (1,0) + // make the (1,1) tile GRASS. + // checks if tiles don't logically follow the EmptyFieldDirectRule + @Test + public void EmptyFieldTestFailTop() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailTop", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + //change the board's cells considering breaking the EmptyField rule + TreeTentCell cell1 = board.getCell(1, 1); + cell1.setData(TreeTentType.GRASS); + board.addModifiedData(cell1); + + // confirm there is not a logical following of the EmptyField rule + Assert.assertNotNull(RULE.checkRule(transition)); + + // the cells should not follow the rule + TreeTentCell c; + for (int i = 0; i < board.getWidth(); i++) { + for (int j = 0; j < board.getHeight(); j++) { + c = board.getCell(j, i); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + + // creates a 3x3 puzzle with 1 tree + // tree is at (1,2) + // make the (1,1) tile GRASS. + // checks if tiles don't logically follow the EmptyFieldDirectRule + @Test + public void EmptyFieldTestFailTopBottom() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + //change the board's cells considering breaking the EmptyField rule + TreeTentCell cell1 = board.getCell(1, 1); + cell1.setData(TreeTentType.GRASS); + board.addModifiedData(cell1); + + // confirm there is not a logical following of the EmptyField rule + Assert.assertNotNull(RULE.checkRule(transition)); + + // the cells should not follow the rule + TreeTentCell c; + for (int i = 0; i < board.getWidth(); i++) { + for (int j = 0; j < board.getHeight(); j++) { + c = board.getCell(j, i); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + + // creates a 3x3 puzzle with 1 tree + // tree is at (0,1) + // make the (1,1) tile GRASS. + // checks if tiles don't logically follow the EmptyFieldDirectRule + @Test + public void EmptyFieldTestFailLeft() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + //change the board's cells considering breaking the EmptyField rule + TreeTentCell cell1 = board.getCell(1, 1); + cell1.setData(TreeTentType.GRASS); + board.addModifiedData(cell1); + + // confirm there is not a logical following of the EmptyField rule + Assert.assertNotNull(RULE.checkRule(transition)); + + // the cells should not follow the rule + TreeTentCell c; + for (int i = 0; i < board.getWidth(); i++) { + for (int j = 0; j < board.getHeight(); j++) { + c = board.getCell(j, i); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + + // creates a 3x3 puzzle with 1 tree + // tree is at (2,1) + // make the (1,1) tile GRASS. + // checks if tiles don't logically follow the EmptyFieldDirectRule + @Test + public void EmptyFieldTestFailRight() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + //change the board's cells considering breaking the EmptyField rule + TreeTentCell cell1 = board.getCell(1, 1); + cell1.setData(TreeTentType.GRASS); + board.addModifiedData(cell1); + + // confirm there is not a logical following of the EmptyField rule + Assert.assertNotNull(RULE.checkRule(transition)); + + // the cells should not follow the rule + TreeTentCell c; + for (int i = 0; i < board.getWidth(); i++) { + for (int j = 0; j < board.getHeight(); j++) { + c = board.getCell(j, i); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } } diff --git a/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java index 8dbec657a..2517df563 100644 --- a/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java @@ -15,6 +15,8 @@ import org.junit.Test; import java.awt.*; +import java.util.List; +import java.util.ArrayList; public class FinishWithGrassDirectRuleTest { @@ -27,15 +29,24 @@ public static void setUp() { treetent = new TreeTent(); } + /** + * 3x3 TreeTent puzzle with a tent at (0,0) + * Tests FinishWithGrassDirectRule on GRASS tiles horizontal of the tent + * at (1,0) and (2,0) + * + * @throws InvalidFileFormatException + */ @Test - public void EmptyFieldTest() throws InvalidFileFormatException { - TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrass", treetent); + public void FinishWithGrassHorizontalTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); + // get board state TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + // change the board's cells considering the FinishWithGrass rule TreeTentCell cell1 = board.getCell(1, 0); cell1.setData(TreeTentType.GRASS); TreeTentCell cell2 = board.getCell(2, 0); @@ -44,21 +55,316 @@ public void EmptyFieldTest() throws InvalidFileFormatException { board.addModifiedData(cell1); board.addModifiedData(cell2); + // confirm there is a logical following of the EmptyField rule Assert.assertNull(RULE.checkRule(transition)); + // only the cell above should change following the rule + TreeTentCell c; for (int i = 0; i < board.getHeight(); i++) { for (int k = 0; k < board.getWidth(); k++) { - Point point = new Point(k, i); - if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { - Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation()) || c.getLocation().equals(cell2.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); } else { - Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); } } } } -} + /** + * 3x3 TreeTent puzzle with a tent at (0,0) + * Tests FinishWithGrassDirectRule on GRASS tiles vertical of the tent + * at (0,1) and (0,2) + * + * @throws InvalidFileFormatException + */ + @Test + public void FinishWithGrassVerticalTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + // change the board's cells considering the FinishWithGrass rule + TreeTentCell cell1 = board.getCell(0, 1); + cell1.setData(TreeTentType.GRASS); + TreeTentCell cell2 = board.getCell(0, 2); + cell2.setData(TreeTentType.GRASS); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + + // confirm there is a logical following of the EmptyField rule + Assert.assertNull(RULE.checkRule(transition)); + + // only the cell above should change following the rule + TreeTentCell c; + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation()) || c.getLocation().equals(cell2.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + + /** + * 3x3 TreeTent puzzle with a tent at (0,0) + * Tests FinishWithGrassDirectRule on GRASS tiles + * at (1,0), (2,0), (0,1), and (0,2) + * + * @throws InvalidFileFormatException + */ + @Test + public void FinishWithGrassTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + // change the board's cells considering the FinishWithGrass rule + TreeTentCell cell1 = board.getCell(1, 0); + cell1.setData(TreeTentType.GRASS); + TreeTentCell cell2 = board.getCell(2, 0); + cell2.setData(TreeTentType.GRASS); + TreeTentCell cell3 = board.getCell(0, 1); + cell3.setData(TreeTentType.GRASS); + TreeTentCell cell4 = board.getCell(0, 2); + cell4.setData(TreeTentType.GRASS); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + board.addModifiedData(cell3); + board.addModifiedData(cell4); + + // confirm there is a logical following of the EmptyField rule + Assert.assertNull(RULE.checkRule(transition)); + + // only the cell above should change following the rule + TreeTentCell c; + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation()) || + c.getLocation().equals(cell2.getLocation()) || + c.getLocation().equals(cell3.getLocation()) || + c.getLocation().equals(cell4.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + + /** + * 3x3 TreeTent puzzle with no tents + * Tests FinishWithGrassDirectRule on GRASS tiles + * GRASS tiles fill entire board + * + * @throws InvalidFileFormatException + */ + @Test + public void NoTentTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/NoTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + // change the board's cells considering the FinishWithGrass rule + List cells = new ArrayList(); + for (int i = 0; i < board.getWidth(); i++) { + for (int k = 0; k < board.getHeight(); k++) { + TreeTentCell c = board.getCell(i, k); + c.setData(TreeTentType.GRASS); + cells.add(c); + } + } + + for (TreeTentCell c : cells) { + board.addModifiedData(c); + } + + // confirm there is a logical following of the EmptyField rule + Assert.assertNull(RULE.checkRule(transition)); + + // all cells should change following the rule + for (TreeTentCell c : cells) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + } + /** + * 3x3 TreeTent puzzle with a tent at (1,1) + * Tests FinishWithGrassDirectRule on GRASS tiles surrounding the tent + * at (1,0), (0,1), (2,1), and (1,2) + * + * @throws InvalidFileFormatException + */ + @Test + public void MiddleTentTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/MiddleTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + // change the board's cells considering the FinishWithGrass rule + TreeTentCell cell1 = board.getCell(1, 0); + TreeTentCell cell2 = board.getCell(0, 1); + TreeTentCell cell3 = board.getCell(2, 1); + TreeTentCell cell4 = board.getCell(1, 2); + + cell1.setData(TreeTentType.GRASS); + cell2.setData(TreeTentType.GRASS); + cell3.setData(TreeTentType.GRASS); + cell4.setData(TreeTentType.GRASS); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + board.addModifiedData(cell3); + board.addModifiedData(cell4); + + // confirm there is a logical following of the EmptyField rule + Assert.assertNull(RULE.checkRule(transition)); + + // only the cell above should change following the rule + TreeTentCell c; + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation()) || + c.getLocation().equals(cell2.getLocation()) || + c.getLocation().equals(cell3.getLocation()) || + c.getLocation().equals(cell4.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + + /** + * 3x3 TreeTent puzzle with missing tents + * Tests FinishWithGrassDirectRule on GRASS tiles filling the puzzle + * all GRASS tiles should fail the FinishWithGrassDirectRule + * + * @throws InvalidFileFormatException + */ + @Test + public void FailTentTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/FailTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + // change the board's cells not following the FinishWithGrass rule + List cells = new ArrayList(); + for (int i = 0; i < board.getWidth(); i++) { + for (int k = 0; k < board.getHeight(); k++) { + TreeTentCell c = board.getCell(i, k); + c.setData(TreeTentType.GRASS); + cells.add(c); + } + } + + for (TreeTentCell c : cells) { + board.addModifiedData(c); + } + + // confirm there is a logical following of the EmptyField rule + Assert.assertNotNull(RULE.checkRule(transition)); + + // all cells should fail the rule test + for (TreeTentCell c : cells) { + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + /** + * 7x7 TreeTent puzzle with multiple tents spaced out + * Tests FinishWithGrassDirectRule on GRASS tiles between the tents + * at (0,3), (2,3), (4,3), and (6,3) + * + * @throws InvalidFileFormatException + */ + @Test + public void SpacedOutTentTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithGrassDirectRule/SpacedOutTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + // get board state + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + // change the board's cells considering the FinishWithGrass rule + TreeTentCell cell1 = board.getCell(0, 3); + TreeTentCell cell2 = board.getCell(2, 3); + TreeTentCell cell3 = board.getCell(4, 3); + TreeTentCell cell4 = board.getCell(6, 3); + + cell1.setData(TreeTentType.GRASS); + cell2.setData(TreeTentType.GRASS); + cell3.setData(TreeTentType.GRASS); + cell4.setData(TreeTentType.GRASS); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + board.addModifiedData(cell3); + board.addModifiedData(cell4); + + // confirm there is a logical following of the EmptyField rule + Assert.assertNull(RULE.checkRule(transition)); + + // only the cell above should change following the rule + TreeTentCell c; + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + c = board.getCell(k, i); + if (c.getLocation().equals(cell1.getLocation()) || + c.getLocation().equals(cell2.getLocation()) || + c.getLocation().equals(cell3.getLocation()) || + c.getLocation().equals(cell4.getLocation())) { + // logically follows + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + // does not use the rule to logically follow + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } +} \ No newline at end of file diff --git a/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java index 6c1468c50..725c3c9de 100644 --- a/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java @@ -15,6 +15,7 @@ import org.junit.Test; import java.awt.*; +import java.util.*; public class FinishWithTentsDirectRuleTest { @@ -26,9 +27,94 @@ public static void setUp() { MockGameBoardFacade.getInstance(); treetent = new TreeTent(); } + + /** + * 3x3 TreeTent puzzle with a GRASS tile at (0,0) + * Tests FinishWithTentsDirectRule on TENT tiles horizontal of the GRASS tile + * at (1,0) and (2,0) + * + * @throws InvalidFileFormatException + */ + @Test + public void FinishWithHorizontalTentsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithHorizontalTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(1, 0); + cell1.setData(TreeTentType.TENT); + TreeTentCell cell2 = board.getCell(2, 0); + cell2.setData(TreeTentType.TENT); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + TreeTentCell c = board.getCell(k, i); + if ((c.getLocation()).equals(cell1.getLocation()) || (c.getLocation()).equals(cell2.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + /** + * 3x3 TreeTent puzzle with a GRASS tile at (0,0) + * Tests FinishWithTentsDirectRule on TENT tiles vertical of the GRASS tile + * at (0,1) and (0,2) + * + * @throws InvalidFileFormatException + */ @Test - public void EmptyFieldTest() throws InvalidFileFormatException { + public void FinishWithVerticalTentsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithVerticalTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0, 1); + cell1.setData(TreeTentType.TENT); + TreeTentCell cell2 = board.getCell(0, 2); + cell2.setData(TreeTentType.TENT); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + TreeTentCell c = board.getCell(k, i); + if ((c.getLocation()).equals(cell1.getLocation()) || (c.getLocation()).equals(cell2.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + + /** + * 3x3 TreeTent puzzle with a GRASS tile at (1,1) + * Tests FinishWithTentsDirectRule on TENT tiles around the GRASS tile + * at (1,0), (1,2), (0,1), and (2,1) + * + * @throws InvalidFileFormatException + */ + @Test + public void FinishWithTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTents", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); @@ -37,24 +123,235 @@ public void EmptyFieldTest() throws InvalidFileFormatException { TreeTentBoard board = (TreeTentBoard) transition.getBoard(); TreeTentCell cell1 = board.getCell(1, 0); + TreeTentCell cell2 = board.getCell(1, 2); + TreeTentCell cell3 = board.getCell(0, 1); + TreeTentCell cell4 = board.getCell(2, 1); + cell1.setData(TreeTentType.TENT); - TreeTentCell cell2 = board.getCell(2, 0); cell2.setData(TreeTentType.TENT); + cell3.setData(TreeTentType.TENT); + cell4.setData(TreeTentType.TENT); board.addModifiedData(cell1); board.addModifiedData(cell2); + board.addModifiedData(cell3); + board.addModifiedData(cell4); Assert.assertNull(RULE.checkRule(transition)); for (int i = 0; i < board.getHeight(); i++) { for (int k = 0; k < board.getWidth(); k++) { - Point point = new Point(k, i); - if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { - Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + TreeTentCell c = board.getCell(k, i); + if ((c.getLocation()).equals(cell1.getLocation()) || + (c.getLocation()).equals(cell2.getLocation()) || + (c.getLocation()).equals(cell3.getLocation()) || + (c.getLocation()).equals(cell4.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, c)); } else { - Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + + /** + * 3x3 TreeTent puzzle with a TENT tile at (1,1) + * Tests FinishWithTentsDirectRule on TENT tiles around the TENT tile + * at (1,0), (1,2), (0,1), and (2,1) + * + * @throws InvalidFileFormatException + */ + @Test + public void AdditionalTentsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/AdditionalTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(1, 0); + TreeTentCell cell2 = board.getCell(1, 2); + TreeTentCell cell3 = board.getCell(0, 1); + TreeTentCell cell4 = board.getCell(2, 1); + + cell1.setData(TreeTentType.TENT); + cell2.setData(TreeTentType.TENT); + cell3.setData(TreeTentType.TENT); + cell4.setData(TreeTentType.TENT); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + board.addModifiedData(cell3); + board.addModifiedData(cell4); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + TreeTentCell c = board.getCell(k, i); + if ((c.getLocation()).equals(cell1.getLocation()) || + (c.getLocation()).equals(cell2.getLocation()) || + (c.getLocation()).equals(cell3.getLocation()) || + (c.getLocation()).equals(cell4.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, c)); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, c)); + } + } + } + } + + /** + * Empty 3x3 TreeTent puzzle + * Tests FinishWithTentsDirectRule on TENT tiles of entire puzzle + * all TENT tiles should fail FinishWithTentsDirectRule + * as no TENT tiles should be there + * + * @throws InvalidFileFormatException + */ + @Test + public void FinishWithTentsFailTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsFail", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + ArrayList cells = new ArrayList(); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + TreeTentCell c = board.getCell(k, i); + c.setData(TreeTentType.TENT); + board.addModifiedData(c); + cells.add(c); + } + } + + Assert.assertNotNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + + /** + * 3x3 TreeTent puzzle with a TENT tile at (1,1) + * Tests FinishWithTentsDirectRule on TENT tiles around the TENT tile + * at (1,0), (1,2), (0,1), and (2,1) + * all TENT tiles should fail FinishWithTentsDirectRule + * as there were already sufficient number of TENT tiles + * + * @throws InvalidFileFormatException + */ + @Test + public void TooManyTentsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/TooManyTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + ArrayList cells = new ArrayList(); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + if((k == 1)&&(i == 1)) { + continue; } + TreeTentCell c = board.getCell(k, i); + c.setData(TreeTentType.TENT); + board.addModifiedData(c); + cells.add(c); + } + } + + Assert.assertNotNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + + /** + * 3x3 TreeTent puzzle with a TENT tile at (1,1) + * Tests FinishWithTentsDirectRule on TENT tiles around the TENT tile + * at (1,0), (1,2), (0,1), and (2,1) + * all TENT tiles should fail FinishWithTentsDirectRule + * as there are multiple configurations of the placement + * of the TENT tiles + * + * @throws InvalidFileFormatException + */ + @Test + public void AmbiguousTentsTest () throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/FinishWithTentsDirectRule/AmbiguousTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell = board.getCell(0, 1); + cell.setData(TreeTentType.TENT); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + + cell.setData(TreeTentType.UNKNOWN); + board.addModifiedData(cell); + cell = board.getCell(1, 0); + cell.setData(TreeTentType.TENT); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + + cell.setData(TreeTentType.UNKNOWN); + board.addModifiedData(cell); + cell = board.getCell(2, 1); + cell.setData(TreeTentType.TENT); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + + cell.setData(TreeTentType.UNKNOWN); + board.addModifiedData(cell); + cell = board.getCell(1, 2); + cell.setData(TreeTentType.TENT); + board.addModifiedData(cell); + + Assert.assertNotNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); } } } diff --git a/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java index 415b4f4b9..3e1b390fb 100644 --- a/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java @@ -27,9 +27,14 @@ public static void setUp() { treetent = new TreeTent(); } + /** + * @throws InvalidFileFormatException + * + * Checks if a test works for an empty square above a tree which is surrounded on all other sides. + */ @Test - public void EmptyFieldTest() throws InvalidFileFormatException { - TestUtilities.importTestBoard("puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpot", treetent); + public void EmptyFieldTest_Up() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotUp", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); @@ -55,6 +60,108 @@ public void EmptyFieldTest() throws InvalidFileFormatException { } } } + + /** + * @throws InvalidFileFormatException + * + * Checks if a test works for an empty square below a tree which is surrounded on all other sides. + */ + @Test + public void EmptyFieldTest_Down() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotDown", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(1, 2); + cell1.setData(TreeTentType.TENT); + + board.addModifiedData(cell1); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * + * Checks if a test works for an empty square to the left of a tree which is surrounded on all other sides. + */ + @Test + public void EmptyFieldTest_Left() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotLeft", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0, 1); + cell1.setData(TreeTentType.TENT); + + board.addModifiedData(cell1); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * + * Checks if a test works for an empty square to the right of a tree which is surrounded on all other sides. + */ + @Test + public void EmptyFieldTest_Right() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotRight", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(2, 1); + cell1.setData(TreeTentType.TENT); + + board.addModifiedData(cell1); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } } diff --git a/src/test/java/puzzles/treetent/rules/NoTentForTreeContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/NoTentForTreeContradictionRuleTest.java index b2d47e222..52aea28c0 100644 --- a/src/test/java/puzzles/treetent/rules/NoTentForTreeContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/NoTentForTreeContradictionRuleTest.java @@ -28,8 +28,12 @@ public static void setUp() { treetent = new TreeTent(); } + /** + * @throws InvalidFileFormatException + * Tests if a tree is next to only grass in a 2x2 grid triggers the contradiction + */ @Test - public void NoTentForTreeContradictionRule_() throws InvalidFileFormatException { + public void NoTentForTreeContradictionRule_Basic() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTree", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); @@ -43,5 +47,65 @@ public void NoTentForTreeContradictionRule_() throws InvalidFileFormatException Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); } + + /** + * @throws InvalidFileFormatException + * Tests similarly to above, but now with a tent diagonally next to the tree, which should still contradict + */ + @Test + public void NoTentForTreeContradictionRule_Diagonal() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeDiagonal", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + + /** + * @throws InvalidFileFormatException + * Tests that adjacent trees do not allow a pass + */ + @Test + public void NoTentForTreeContradictionRule_TwoTrees() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTrees", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + + /** + * @throws InvalidFileFormatException + * Tests similarly to above, but now with a tent diagonally next to two trees, which should still contradict on one. + */ + @Test + public void NoTentForTreeContradictionRule_TwoTreesDiagonal() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTreesDiagonal", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } } diff --git a/src/test/java/puzzles/treetent/rules/NoTreeForTentContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/NoTreeForTentContradictionRuleTest.java index c3003cef1..2ad2ac90e 100644 --- a/src/test/java/puzzles/treetent/rules/NoTreeForTentContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/NoTreeForTentContradictionRuleTest.java @@ -10,13 +10,9 @@ import edu.rpi.legup.puzzle.treetent.TreeTent; import edu.rpi.legup.puzzle.treetent.TreeTentBoard; -import edu.rpi.legup.puzzle.treetent.TreeTentCell; -import edu.rpi.legup.puzzle.treetent.TreeTentType; import edu.rpi.legup.puzzle.treetent.rules.NoTreeForTentContradictionRule; import edu.rpi.legup.save.InvalidFileFormatException; -import java.awt.*; - public class NoTreeForTentContradictionRuleTest { private static final NoTreeForTentContradictionRule RULE = new NoTreeForTentContradictionRule(); @@ -28,9 +24,13 @@ public static void setUp() { treetent = new TreeTent(); } + /** + * @throws InvalidFileFormatException + * Tests if, in a 2x2 Grid, a Tent in the NW corner has no adjacent trees + */ @Test - public void NoTreeForTentContradictionRule_() throws InvalidFileFormatException { - TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent", treetent); + public void NoTreeForTentContradictionRule_NW() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNW", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); @@ -43,5 +43,165 @@ public void NoTreeForTentContradictionRule_() throws InvalidFileFormatException Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 2x2 Grid, a Tent in the NE corner has no adjacent trees + */ + @Test + public void NoTreeForTentContradictionRule_NE() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNE", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 2x2 Grid, a Tent in the NW corner has no adjacent trees + */ + @Test + public void NoTreeForTentContradictionRule_SW() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSW", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 2x2 Grid, a Tent in the SE corner has no adjacent trees + */ + @Test + public void NoTreeForTentContradictionRule_SE() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSE", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 3x3 Grid with no trees, a Tent in the center cell has no adjacent trees + */ + @Test + public void NoTreeForTentContradictionRule_3x3() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent3x3", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 2))); + } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 3x3 Grid with diagonal trees, a Tent in the center cell has no adjacent trees + */ + @Test + public void NoTreeForTentContradictionRule_3x3WithDiagonalTrees() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentDiagonals", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 2))); + } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 3x3 Grid with an adjacent tree, test does not assert null. + */ + @Test + public void NoTreeForTentContradictionRule_YesTree() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentYesTree", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNotNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 2))); + } + + /** + * @throws InvalidFileFormatException + * Tests if, in a 3x3 Grid with touching tents, a Tent in the center cell has no adjacent trees + */ + @Test + public void NoTreeForTentContradictionRule_JustTent() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentJustTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 2))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(2, 2))); + } } diff --git a/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java index 14afb4dc0..999405747 100644 --- a/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java @@ -27,6 +27,10 @@ public static void setUp() { treetent = new TreeTent(); } + /** + * @throws InvalidFileFormatException + * Test to check if all adjacent and diagonals not filled with a tree are filled with grass + */ @Test public void SurroundTentWithGrassBasicRuleTest() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrass", treetent); @@ -58,6 +62,90 @@ public void SurroundTentWithGrassBasicRuleTest() throws InvalidFileFormatExcepti } } } + + /** + * @throws InvalidFileFormatException + * + * Test with a 3x3 board with an absolutely empty area aside from a tent in the middle + * While such a situation is an illegal treetent setup, this direct rule doesn't consider that aspect, so its ok in this context + */ + @Test + public void SurroundTentWithGrassBasicRuleTest_BadBoard() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassBad", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0, 0); + cell1.setData(TreeTentType.GRASS); + TreeTentCell cell2 = board.getCell(1, 0); + cell2.setData(TreeTentType.GRASS); + TreeTentCell cell3 = board.getCell(2, 0); + cell3.setData(TreeTentType.GRASS); + TreeTentCell cell4 = board.getCell(0, 1); + cell4.setData(TreeTentType.GRASS); + //Skip (1,1) due to being the Tent + TreeTentCell cell5 = board.getCell(2, 1); + cell5.setData(TreeTentType.GRASS); + TreeTentCell cell6 = board.getCell(0, 2); + cell6.setData(TreeTentType.GRASS); + TreeTentCell cell7 = board.getCell(1, 2); + cell7.setData(TreeTentType.GRASS); + TreeTentCell cell8 = board.getCell(2, 2); + cell8.setData(TreeTentType.GRASS); + + board.addModifiedData(cell1); + board.addModifiedData(cell2); + board.addModifiedData(cell3); + //board.addModifiedData(cell4); + board.addModifiedData(cell5); + board.addModifiedData(cell6); + board.addModifiedData(cell7); + board.addModifiedData(cell8); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation()) || + point.equals(cell3.getLocation()) || //point.equals(cell4.getLocation()) || + point.equals(cell5.getLocation()) || point.equals(cell6.getLocation()) || + point.equals(cell7.getLocation()) || point.equals(cell8.getLocation()) + ) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * + * Test to see if the rule passes even if no grass was able to be placed due to the presence of trees. + */ + @Test + public void SurroundTentWithGrassBasicRuleTest_FullBoard() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassTrees", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkRule(transition)); + + for (int i = 0; i < board.getHeight(); i++){ + for (int k = 0; k < board.getWidth(); k++){ + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } } diff --git a/src/test/java/puzzles/treetent/rules/TentOrGrassCaseRuleTest.java b/src/test/java/puzzles/treetent/rules/TentOrGrassCaseRuleTest.java new file mode 100644 index 000000000..4ec8b4e36 --- /dev/null +++ b/src/test/java/puzzles/treetent/rules/TentOrGrassCaseRuleTest.java @@ -0,0 +1,83 @@ +package puzzles.treetent.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.treetent.TreeTent; +import edu.rpi.legup.puzzle.treetent.TreeTentBoard; +import edu.rpi.legup.puzzle.treetent.TreeTentCell; +import edu.rpi.legup.puzzle.treetent.TreeTentType; +import edu.rpi.legup.puzzle.treetent.rules.TentOrGrassCaseRule; +import edu.rpi.legup.save.InvalidFileFormatException; +import legup.MockGameBoardFacade; +import legup.TestUtilities; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.awt.*; +import java.util.ArrayList; + +public class TentOrGrassCaseRuleTest { + private static final TentOrGrassCaseRule RULE = new TentOrGrassCaseRule(); + private static TreeTent treetent; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + treetent = new TreeTent(); + } + + /** + * empty 3x3 TreeTent puzzle + * Tests TentOrGrassCaseRule on UNKOWN tile + * at (0,0) + * + * checks 2 cases are created + * checks first case is TENT tile + * checks second case is GRASS tile + * checks other cells have not been modified + * + * @throws InvalidFileFormatException + */ + @Test + public void TentOrTreeTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TentOrGrassCaseRule/TestPuzzle", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell testing_cell = board.getCell(0, 0); + ArrayList cases = RULE.getCases(board, testing_cell); + + // assert correct number of cases created + Assert.assertEquals(2, cases.size()); + + // TENT case + TreeTentBoard tentCase = (TreeTentBoard) cases.get(0); + Assert.assertEquals(tentCase.getCell(0, 0).getType(), TreeTentType.TENT); + + // GRASS case + TreeTentBoard grassCase = (TreeTentBoard) cases.get(1); + Assert.assertEquals(grassCase.getCell(0, 0).getType(), TreeTentType.GRASS); + + // checks other cells have not been modified + TreeTentCell original_cell; + TreeTentCell case_cell; + + for (int w =0; w < board.getWidth(); w++) { + for (int h = 0; h < board.getHeight(); h++) { + if (w == 0 && h ==0) { + continue; + } + original_cell = board.getCell(w, h); + case_cell = tentCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + + case_cell = grassCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } +} diff --git a/src/test/java/puzzles/treetent/rules/TooFewTentsContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/TooFewTentsContradictionRuleTest.java index bfcb80a23..a5999dc6e 100644 --- a/src/test/java/puzzles/treetent/rules/TooFewTentsContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TooFewTentsContradictionRuleTest.java @@ -1,5 +1,6 @@ package puzzles.treetent.rules; +import edu.rpi.legup.puzzle.treetent.TreeTentCell; import legup.MockGameBoardFacade; import legup.TestUtilities; import edu.rpi.legup.model.tree.TreeNode; @@ -10,8 +11,6 @@ import edu.rpi.legup.puzzle.treetent.TreeTent; import edu.rpi.legup.puzzle.treetent.TreeTentBoard; -import edu.rpi.legup.puzzle.treetent.TreeTentCell; -import edu.rpi.legup.puzzle.treetent.TreeTentType; import edu.rpi.legup.puzzle.treetent.rules.TooFewTentsContradictionRule; import edu.rpi.legup.save.InvalidFileFormatException; @@ -28,9 +27,46 @@ public static void setUp() { treetent = new TreeTent(); } + /** + * @throws InvalidFileFormatException + * Using a 1x1 Puzzle Grid, which is just grass, checks if the fact it expects a tent on the y-axis is caught. + */ + @Test + public void TooFewTentsContradictionRule_JustY() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsJustY", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + } + + /** + * @throws InvalidFileFormatException + * Using a 1x1 Puzzle Grid, which is just a tent, checks if the fact it expects 2 tents on the y-axis is caught. + * (This is an impossible situation given the constraints, but for the purposes of the test it is fine) + */ + @Test + public void TooFewTentsContradictionRule_WithTent() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsWithTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + } + + /** + * @throws InvalidFileFormatException + * Using a 1x1 Puzzle Grid, which is just grass, checks if the fact it expects a tent on both x and y is caught. + */ @Test - public void TooFewTentsContradictionRule_() throws InvalidFileFormatException { - TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents", treetent); + public void TooFewTentsContradictionRule_DoubleBad() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsDoubleBad", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); @@ -39,5 +75,177 @@ public void TooFewTentsContradictionRule_() throws InvalidFileFormatException { Assert.assertNull(RULE.checkContradiction(board)); Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); } + + /** + * @throws InvalidFileFormatException + * Looks at a 2x2 Board in the format: + * [] Tr + * [] Gr + * Column 2 is checked to have 1 Tent (which is not present, thus producing a contradiction) + */ + @Test + public void TooFewTentsContradictionRule_2x2ColumnOnly() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Column",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + + TreeTentCell cell1 = board.getCell(1,0); + TreeTentCell cell2 = board.getCell(1,1); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Looks at a 2x2 Board in the format: + * Tr Gr + * [] [] + * Row 1 is checked to have 1 Tent (which is not present, thus producing a contradiction) + */ + @Test + public void TooFewTentsContradictionRule_2x2RowOnly() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Row",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + + TreeTentCell cell1 = board.getCell(0,0); + TreeTentCell cell2 = board.getCell(1,0); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Looks at a 3x3 Board in the format: + * [] Tr [] + * [] Gr [] + * [] Gr [] + * Column 2 is checked to have 1 Tent (which is not present, thus producing a contradiction) + */ + @Test + public void TooFewTentsContradictionRule_3x3OneColumn() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3Column",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + + TreeTentCell cell1 = board.getCell(1,0); + TreeTentCell cell2 = board.getCell(1,1); + TreeTentCell cell3 = board.getCell(1,2); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation()) || point.equals(cell3.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Looks at a 3x3 Board in the format: + * Gr Tr Gr + * Gr [] Gr + * Gr Tr Gr + * Column 1 and 3 are checked to have 1 Tent (which is not present, thus producing a contradiction) + */ + @Test + public void TooFewTentsContradictionRule_3x3TwoColumn() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3DoubleColumn",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + + TreeTentCell cell1 = board.getCell(0,0); + TreeTentCell cell2 = board.getCell(0,1); + TreeTentCell cell3 = board.getCell(0,2); + TreeTentCell cell4 = board.getCell(2,0); + TreeTentCell cell5 = board.getCell(2,1); + TreeTentCell cell6 = board.getCell(2,2); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation()) || point.equals(cell3.getLocation()) || + point.equals(cell4.getLocation()) || point.equals(cell5.getLocation()) || point.equals(cell6.getLocation())) { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Looks at a 2x2 Board in the format: + * Tn [] + * Tr [] + * This should fail the contradiction as it is a legal board. + */ + @Test + public void TooFewTentsContradictionRule_NoContradiction() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsNoContradiction",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNotNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + + + } diff --git a/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java index 2845c7b25..2a351556b 100644 --- a/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java @@ -28,17 +28,162 @@ public static void setUp() { treetent = new TreeTent(); } + /* + TESTING BASIS: + All test in this Rule use a 3x3 table. + There is a Tree at (1,1) + There are tents at (0,1) and (2,2) + All Tent Counts are listed left to right or top to bottom + */ + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTents if: + * Row Tent Counts: 0,0,0 + * Column Tent Counts: 0,0,0 + */ + @Test + public void TooManyTentsContradictionRule_TotalFail() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTotalFail",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0,1); + + Assert.assertNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation())) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTents if: + * Row Tent Counts: 1,0,0 + * Column Tent Counts: 0,0,0 + */ + @Test + public void TooManyTentsContradictionRule_TopRight() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopRight",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0,0); + TreeTentCell cell2 = board.getCell(0,1); + + Assert.assertNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTests if: + * Row Tent Counts: 0,0,1 + * Column Tent Counts: 0,0,0 + */ + @Test + public void TooManyTentsContradictionRule_BottomRight() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomRight",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0,1); + TreeTentCell cell2 = board.getCell(0,2); + + Assert.assertNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTents if: + * Row Tent Counts: 0,0,0 + * Column Tent Counts: 0,1,0 + */ + @Test + public void TooManyTentsContradictionRule_TopDown() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopDown",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0,1); + TreeTentCell cell2 = board.getCell(1,1); + + Assert.assertNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation())) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTents if: + * Row Tent Counts: 0,0,0 + * Column Tent Counts: 0,0,1 + */ @Test - public void TooManyTentsContradictionRule_Column_Row() throws InvalidFileFormatException { - TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsContradictionRuleColumn_Row", treetent); + public void TooManyTentsContradictionRule_BottomDown() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomDown",treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); TreeTentBoard board = (TreeTentBoard) transition.getBoard(); - TreeTentCell cell1 = board.getCell(0, 1); - TreeTentCell cell2 = board.getCell(2, 1); + TreeTentCell cell1 = board.getCell(0,1); + TreeTentCell cell2 = board.getCell(2,1); Assert.assertNull(RULE.checkContradiction(board)); @@ -49,9 +194,78 @@ public void TooManyTentsContradictionRule_Column_Row() throws InvalidFileFormatE Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); } else { - // The TooManyTentsContradictionRule checks the col and row the cell is in - // Therefore, even if a cell(0, 0) is empty, it follows the contradiction rule because - // the row it is in follows the contradiciton rule. (And because cell(1, 0) has tent row tent total is 0) + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTents if the Top Tent is completely accounted for, but not the bottom + * Row Tent Counts: 1,0,0 + * Column Tent Counts: 0,1,0 + */ + @Test + public void TooManyTentsContradictionRule_TopAccount() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopAccount",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0,0); + TreeTentCell cell2 = board.getCell(1,0); + TreeTentCell cell3 = board.getCell(0,1); + TreeTentCell cell4 = board.getCell(1,1); + + Assert.assertNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation()) || + point.equals(cell3.getLocation()) || point.equals(cell4.getLocation())) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + } + } + } + + /** + * @throws InvalidFileFormatException + * Tests for TooManyTents if the Bottom Tent is completely accounted for, but not the Top + * Row Tent Counts: 0,0,1 + * Column Tent Counts: 0,0,1 + */ + @Test + public void TooManyTentsContradictionRule_BottomAccount() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomAccount",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + TreeTentCell cell1 = board.getCell(0,1); + TreeTentCell cell2 = board.getCell(2,1); + TreeTentCell cell3 = board.getCell(0,2); + TreeTentCell cell4 = board.getCell(2,2); + + Assert.assertNull(RULE.checkContradiction(board)); + + for (int i = 0; i < board.getHeight(); i++) { + for (int k = 0; k < board.getWidth(); k++) { + Point point = new Point(k, i); + if (point.equals(cell1.getLocation()) || point.equals(cell2.getLocation()) || + point.equals(cell3.getLocation()) || point.equals(cell4.getLocation())) { + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); + } + else { Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); } } diff --git a/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java index 79fc70118..f48afe5d7 100644 --- a/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java @@ -10,13 +10,9 @@ import edu.rpi.legup.puzzle.treetent.TreeTent; import edu.rpi.legup.puzzle.treetent.TreeTentBoard; -import edu.rpi.legup.puzzle.treetent.TreeTentCell; -import edu.rpi.legup.puzzle.treetent.TreeTentType; import edu.rpi.legup.puzzle.treetent.rules.TouchingTentsContradictionRule; import edu.rpi.legup.save.InvalidFileFormatException; -import java.awt.*; - public class TouchingTentsContradictionRuleTest { private static final TouchingTentsContradictionRule RULE = new TouchingTentsContradictionRule(); @@ -28,8 +24,14 @@ public static void setUp() { treetent = new TreeTent(); } + //DIAGONAL TESTS + /** + * @throws InvalidFileFormatException + * Tests a tent diagonal of orientation T + * T + **/ @Test - public void TouchingTentsContradictionRule_Diagonal() throws InvalidFileFormatException { + public void TouchingTentsContradictionRule_DiagonalUpLeftToDownRight() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsDiagonal", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); @@ -44,8 +46,35 @@ public void TouchingTentsContradictionRule_Diagonal() throws InvalidFileFormatEx Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); } + /** + * @throws InvalidFileFormatException + * Tests a tent diagonal of orientation T + * T + **/ @Test - public void TouchingTentsContradictionRule_Adjacent() throws InvalidFileFormatException { + public void TouchingTentsContradictionRule_DiagonalDownLeftToUpRight() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsDiagonalAlt",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition,board.getCell(1,0))); + Assert.assertNull(RULE.checkRuleAt(transition,board.getCell(0,1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + + //ADJACENT TESTS + /** + * @throws InvalidFileFormatException + * Tests a tent adjacent of orientation T + * T + **/ + @Test + public void TouchingTentsContradictionRule_AdjacentVertical() throws InvalidFileFormatException { TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsAdjacent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); @@ -59,6 +88,162 @@ public void TouchingTentsContradictionRule_Adjacent() throws InvalidFileFormatEx Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); } + + /** + * @throws InvalidFileFormatException + * Tests a tent adjacent of orientation TT + **/ + @Test + public void TouchingTentsContradictionRule_AdjacentHorizontal() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsAdjacentAlt", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + //MIXED TESTS + /** + * @throws InvalidFileFormatException + * Tests a tent of orientation TT + * TT + **/ + @Test + public void TouchingTentsContradictionRule_2By2Square() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsFull2By2",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + /** + * @throws InvalidFileFormatException + * Tests a tent of orientation TT + * T + **/ + @Test + public void TouchingTentsContradictionRule_UpLeft() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpLeft",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + } + /** + * @throws InvalidFileFormatException + * Tests a tent of orientation TT + * T + **/ + @Test + public void TouchingTentsContradictionRule_UpRight() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpRight",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + } + /** + * @throws InvalidFileFormatException + * Tests a tent of orientation T + * TT + **/ + @Test + public void TouchingTentsContradictionRule_DownLeft() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + } + /** + * @throws InvalidFileFormatException + * Tests a tent of orientation T + * TT + **/ + @Test + public void TouchingTentsContradictionRule_DownRight() throws InvalidFileFormatException { + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownRight",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNull(RULE.checkContradiction(board)); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(1, 1))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + } + /** + * @throws InvalidFileFormatException + * Tests if tree adjacent triggers a null + */ + @Test + public void TouchingTentsContradictionRule_TreeAdjacent() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeAdjacent",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNotNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 1))); + } + /** + * @throws InvalidFileFormatException + * Tests if tree diagonal triggers a null + */ + @Test + public void TouchingTentsContradictionRule_TreeDiagonal() throws InvalidFileFormatException{ + TestUtilities.importTestBoard("puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeDiagonal",treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + Assert.assertNotNull(RULE.checkContradiction(board)); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(0, 0))); + Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(1, 0))); + } + } diff --git a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/LightInHorizontalPath b/src/test/resources/puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInHorizontalPath similarity index 84% rename from build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/LightInHorizontalPath rename to src/test/resources/puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInHorizontalPath index 633ccc80b..3c8786e54 100644 --- a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/LightInHorizontalPath +++ b/src/test/resources/puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInHorizontalPath @@ -1,10 +1,11 @@ - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/lightup/rules/CannotLightACellContradictionRule/CanLightTest b/src/test/resources/puzzles/lightup/rules/CannotLightACellContradictionRule/CanLightTest new file mode 100644 index 000000000..4169bf382 --- /dev/null +++ b/src/test/resources/puzzles/lightup/rules/CannotLightACellContradictionRule/CanLightTest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/lightup/rules/EmptyCellinLightDirectRule/EmptyCells b/src/test/resources/puzzles/lightup/rules/EmptyCellinLightDirectRule/EmptyCells index feca5b861..d6fba5369 100644 --- a/src/test/resources/puzzles/lightup/rules/EmptyCellinLightDirectRule/EmptyCells +++ b/src/test/resources/puzzles/lightup/rules/EmptyCellinLightDirectRule/EmptyCells @@ -1,6 +1,6 @@ - + diff --git a/src/test/resources/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/FalseBlackBetweenRegions b/src/test/resources/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/FalseBlackBetweenRegions new file mode 100644 index 000000000..5aecd1575 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/BlackBetweenRegionsDirectRule/FalseBlackBetweenRegions @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/BlackBottleNeckDirectRule/CornerBottleNeck b/src/test/resources/puzzles/nurikabe/rules/BlackBottleNeckDirectRule/CornerBottleNeck new file mode 100644 index 000000000..77f38d5d4 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/BlackBottleNeckDirectRule/CornerBottleNeck @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/BlackBottleNeckDirectRule/FalseBottleNeck b/src/test/resources/puzzles/nurikabe/rules/BlackBottleNeckDirectRule/FalseBottleNeck new file mode 100644 index 000000000..3e3d7610a --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/BlackBottleNeckDirectRule/FalseBottleNeck @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/BlackOrWhiteCaseRule/SimpleBlackOrWhite b/src/test/resources/puzzles/nurikabe/rules/BlackOrWhiteCaseRule/SimpleBlackOrWhite new file mode 100644 index 000000000..fb5e45218 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/BlackOrWhiteCaseRule/SimpleBlackOrWhite @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/BlackSquareContradictionRule/CornerBlackSquare b/src/test/resources/puzzles/nurikabe/rules/BlackSquareContradictionRule/CornerBlackSquare new file mode 100644 index 000000000..98a01d8b5 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/BlackSquareContradictionRule/CornerBlackSquare @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/BlackSquareContradictionRule/FalseBlackSquare b/src/test/resources/puzzles/nurikabe/rules/BlackSquareContradictionRule/FalseBlackSquare new file mode 100644 index 000000000..813114443 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/BlackSquareContradictionRule/FalseBlackSquare @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/CannotReachCellDirectRule/AllCellsReachable b/src/test/resources/puzzles/nurikabe/rules/CannotReachCellDirectRule/AllCellsReachable new file mode 100644 index 000000000..63e38d25f --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/CannotReachCellDirectRule/AllCellsReachable @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/CannotReachCellDirectRule/SimpleUnreachableCell b/src/test/resources/puzzles/nurikabe/rules/CannotReachCellDirectRule/SimpleUnreachableCell new file mode 100644 index 000000000..e11487564 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/CannotReachCellDirectRule/SimpleUnreachableCell @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/CornerBlackDirectRule/FalseCornerBlack b/src/test/resources/puzzles/nurikabe/rules/CornerBlackDirectRule/FalseCornerBlack new file mode 100644 index 000000000..0599fdfa4 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/CornerBlackDirectRule/FalseCornerBlack @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInVerticalPath b/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/CornerBlack1 similarity index 58% rename from build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInVerticalPath rename to src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/CornerBlack1 index 5f27b3ec8..ae078229e 100644 --- a/build/resources/test/puzzles/lightup/rules/BulbsInPathContradictionRule/BlockInVerticalPath +++ b/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/CornerBlack1 @@ -1,10 +1,9 @@ - + - + - diff --git a/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/CornerBlack2 b/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/CornerBlack2 new file mode 100644 index 000000000..f274fc774 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/CornerBlack2 @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/FalseFillinBlack b/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/FalseFillinBlack new file mode 100644 index 000000000..731e2dc74 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/FillinBlackDirectRule/FalseFillinBlack @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/CornerWhite1 b/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/CornerWhite1 new file mode 100644 index 000000000..de0ca4f71 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/CornerWhite1 @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/CornerWhite2 b/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/CornerWhite2 new file mode 100644 index 000000000..9fc228483 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/CornerWhite2 @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/FalseFillinWhite b/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/FalseFillinWhite new file mode 100644 index 000000000..f2599c71f --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/FillinWhiteDirectRule/FalseFillinWhite @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/IsolateBlackContradictionRule/DiagonalIsolateBlack b/src/test/resources/puzzles/nurikabe/rules/IsolateBlackContradictionRule/DiagonalIsolateBlack new file mode 100644 index 000000000..7ff5dcf24 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/IsolateBlackContradictionRule/DiagonalIsolateBlack @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/IsolateBlackContradictionRule/FalseIsolateBlack b/src/test/resources/puzzles/nurikabe/rules/IsolateBlackContradictionRule/FalseIsolateBlack new file mode 100644 index 000000000..b4eb09302 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/IsolateBlackContradictionRule/FalseIsolateBlack @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/MultipleNumbersContradictionRule/ComplexRegion b/src/test/resources/puzzles/nurikabe/rules/MultipleNumbersContradictionRule/ComplexRegion new file mode 100644 index 000000000..5f8e607fe --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/MultipleNumbersContradictionRule/ComplexRegion @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/MultipleNumbersContradictionRule/FalseContradiction b/src/test/resources/puzzles/nurikabe/rules/MultipleNumbersContradictionRule/FalseContradiction new file mode 100644 index 000000000..0f14d6916 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/MultipleNumbersContradictionRule/FalseContradiction @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/NoNumberReachable b/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/FalseNoNumber similarity index 100% rename from src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/NoNumberReachable rename to src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/FalseNoNumber diff --git a/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/FalseNoNumber2 b/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/FalseNoNumber2 new file mode 100644 index 000000000..be1fc64f7 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/FalseNoNumber2 @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/NoNumberSurroundBlack b/src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/SimpleNoNumber similarity index 100% rename from src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/NoNumberSurroundBlack rename to src/test/resources/puzzles/nurikabe/rules/NoNumberContradictionRule/SimpleNoNumber diff --git a/src/test/resources/puzzles/nurikabe/rules/PreventBlackSquareDirectRule/FalseBlackSquare b/src/test/resources/puzzles/nurikabe/rules/PreventBlackSquareDirectRule/FalseBlackSquare new file mode 100644 index 000000000..2fd8e7d35 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/PreventBlackSquareDirectRule/FalseBlackSquare @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/SurroundRegionDirectRule/FalseSurroundRegion b/src/test/resources/puzzles/nurikabe/rules/SurroundRegionDirectRule/FalseSurroundRegion new file mode 100644 index 000000000..5e0b04f68 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/SurroundRegionDirectRule/FalseSurroundRegion @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/TooFewSpacesContradictionRule/FalseTooFewSpaces b/src/test/resources/puzzles/nurikabe/rules/TooFewSpacesContradictionRule/FalseTooFewSpaces new file mode 100644 index 000000000..ca3e9be84 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/TooFewSpacesContradictionRule/FalseTooFewSpaces @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/TooFewSpacesContradictionRule/InsufficientSpace b/src/test/resources/puzzles/nurikabe/rules/TooFewSpacesContradictionRule/InsufficientSpace new file mode 100644 index 000000000..22163947a --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/TooFewSpacesContradictionRule/InsufficientSpace @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/TooManySpacesContradictionRule/ExtraDiagonalSpace b/src/test/resources/puzzles/nurikabe/rules/TooManySpacesContradictionRule/ExtraDiagonalSpace new file mode 100644 index 000000000..5d9ad70e1 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/TooManySpacesContradictionRule/ExtraDiagonalSpace @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/TooManySpacesContradictionRule/MultipleNumberRegion b/src/test/resources/puzzles/nurikabe/rules/TooManySpacesContradictionRule/MultipleNumberRegion new file mode 100644 index 000000000..3ec126199 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/TooManySpacesContradictionRule/MultipleNumberRegion @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/UnreachableWhiteCellContradictionRule/AllCellsReachable b/src/test/resources/puzzles/nurikabe/rules/UnreachableWhiteCellContradictionRule/AllCellsReachable new file mode 100644 index 000000000..dbc5fadb2 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/UnreachableWhiteCellContradictionRule/AllCellsReachable @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/UnreachableWhiteCellContradictionRule/SimpleUnreachableTest b/src/test/resources/puzzles/nurikabe/rules/UnreachableWhiteCellContradictionRule/SimpleUnreachableTest new file mode 100644 index 000000000..3d456bdb0 --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/UnreachableWhiteCellContradictionRule/SimpleUnreachableTest @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/nurikabe/rules/WhiteBottleNeckDirectRule/FalseBottleNeck b/src/test/resources/puzzles/nurikabe/rules/WhiteBottleNeckDirectRule/FalseBottleNeck new file mode 100644 index 000000000..521576aeb --- /dev/null +++ b/src/test/resources/puzzles/nurikabe/rules/WhiteBottleNeckDirectRule/FalseBottleNeck @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/ComplexStatement1_False b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/ComplexStatement1_False new file mode 100644 index 000000000..f7e5824ff --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/ComplexStatement1_False @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/ComplexStatement1_True b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/ComplexStatement1_True new file mode 100644 index 000000000..46dd5e603 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/ComplexStatement1_True @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/SimpleStatement1_False b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/SimpleStatement1_False new file mode 100644 index 000000000..aa3ed2b55 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/SimpleStatement1_False @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/SimpleStatement1_True b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/SimpleStatement1_True new file mode 100644 index 000000000..881a1063e --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndCaseRule/SimpleStatement1_True @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAnd b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAnd new file mode 100644 index 000000000..f6f60abc3 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAnd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownFalse b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownFalse new file mode 100644 index 000000000..d8edf4a76 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownFalse @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownTrue b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownTrue new file mode 100644 index 000000000..364d8faf6 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/FalseAndWithKnownTrue @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/TrueAnd b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/TrueAnd new file mode 100644 index 000000000..307f6d14a --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndEliminationDirectRule/TrueAnd @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUF b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUF new file mode 100644 index 000000000..003792ec0 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUT b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUT new file mode 100644 index 000000000..05803b88d --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUU b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUU new file mode 100644 index 000000000..b97eafdfe --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/FUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUF b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUF new file mode 100644 index 000000000..fc10f77bb --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUT b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUT new file mode 100644 index 000000000..dc99e3cdc --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUU b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUU new file mode 100644 index 000000000..2c592ef86 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/TUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUF b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUF new file mode 100644 index 000000000..39b5fb079 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUF @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUT b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUT new file mode 100644 index 000000000..261c035cd --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUT @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUU b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUU new file mode 100644 index 000000000..d9f415439 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AndIntroductionDirectRule/UUU @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/Empty b/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/Empty new file mode 100644 index 000000000..6a6effadf --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/Empty @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/FalseA b/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/FalseA new file mode 100644 index 000000000..8c5ddc7b9 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/FalseA @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/TrueB b/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/TrueB new file mode 100644 index 000000000..46a1beb2d --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/AtomicDirectRule/TrueB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditional b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditional new file mode 100644 index 000000000..5ea1c8a63 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditional @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseA b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseA new file mode 100644 index 000000000..1f956a743 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseA @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseB b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseB new file mode 100644 index 000000000..49fd4f49f --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithFalseB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueA b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueA new file mode 100644 index 000000000..000a07d91 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueA @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueB b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueB new file mode 100644 index 000000000..18cbd4156 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/FalseBiconditionalWithTrueB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditional b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditional new file mode 100644 index 000000000..cbf64468f --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditional @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseA b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseA new file mode 100644 index 000000000..9655bc7ae --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseA @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseB b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseB new file mode 100644 index 000000000..032fc23df --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithFalseB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueA b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueA new file mode 100644 index 000000000..44381c235 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueA @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueB b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueB new file mode 100644 index 000000000..8e42c0032 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalEliminationDirectRule/TrueBiconditionalWithTrueB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUF b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUF new file mode 100644 index 000000000..817025f78 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUT b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUT new file mode 100644 index 000000000..4bb3cb635 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUU b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUU new file mode 100644 index 000000000..7ddeeb5c8 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/FUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUF b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUF new file mode 100644 index 000000000..fb40ff4d4 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUT b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUT new file mode 100644 index 000000000..6ce5ab64c --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUU b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUU new file mode 100644 index 000000000..9307de3ad --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/TUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUF b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUF new file mode 100644 index 000000000..c61474b96 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUF @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUT b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUT new file mode 100644 index 000000000..2dead7328 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUT @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUU b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUU new file mode 100644 index 000000000..04596d449 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/BiconditionalIntroductionDirectRule/UUU @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/FalseConditional b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/FalseConditional new file mode 100644 index 000000000..2da458f51 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/FalseConditional @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditional b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditional new file mode 100644 index 000000000..829861f75 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditional @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithFalseB b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithFalseB new file mode 100644 index 000000000..85e42664a --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithFalseB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueA b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueA new file mode 100644 index 000000000..d77a27502 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueA @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueB b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueB new file mode 100644 index 000000000..86b10a7cc --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalEliminationDirectRule/TrueConditionalWithTrueB @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUF b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUF new file mode 100644 index 000000000..a2adf2297 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUT b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUT new file mode 100644 index 000000000..5b849c7ac --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUU b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUU new file mode 100644 index 000000000..48d5fd7c6 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/FUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUF b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUF new file mode 100644 index 000000000..480a409ef --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUT b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUT new file mode 100644 index 000000000..862ee1628 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUU b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUU new file mode 100644 index 000000000..79b97ba46 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/TUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUF b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUF new file mode 100644 index 000000000..e5c9c4c0d --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUF @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUT b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUT new file mode 100644 index 000000000..efe86b390 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUT @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUU b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUU new file mode 100644 index 000000000..b0aa8ba00 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/ConditionalIntroductionDirectRule/UUU @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/BlankNot b/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/BlankNot new file mode 100644 index 000000000..e7bf96e4a --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/BlankNot @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/FalseNot b/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/FalseNot new file mode 100644 index 000000000..2e9ac998d --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/FalseNot @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/TrueNot b/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/TrueNot new file mode 100644 index 000000000..6f19fc871 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/NotEliminationDirectRule/TrueNot @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/BlankA b/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/BlankA new file mode 100644 index 000000000..e7bf96e4a --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/BlankA @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/FalseA b/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/FalseA new file mode 100644 index 000000000..d4c178464 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/FalseA @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/TrueA b/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/TrueA new file mode 100644 index 000000000..7c4f71984 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/NotIntroductionDirectRule/TrueA @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/ComplexStatement1_False b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/ComplexStatement1_False new file mode 100644 index 000000000..1da467289 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/ComplexStatement1_False @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/ComplexStatement1_True b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/ComplexStatement1_True new file mode 100644 index 000000000..e8067987e --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/ComplexStatement1_True @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/SimpleStatement1_False b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/SimpleStatement1_False new file mode 100644 index 000000000..4daaabc88 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/SimpleStatement1_False @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/SimpleStatement1_True b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/SimpleStatement1_True new file mode 100644 index 000000000..765aad7d8 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrCaseRule/SimpleStatement1_True @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/FTU b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/FTU new file mode 100644 index 000000000..bda22c0e6 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/FTU @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UFU b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UFU new file mode 100644 index 000000000..b7c23215e --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UFU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTF b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTF new file mode 100644 index 000000000..60eaca2b8 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTU b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTU new file mode 100644 index 000000000..c28ba1fde --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrEliminationDirectRule/UTU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUF b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUF new file mode 100644 index 000000000..2326f8df4 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUT b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUT new file mode 100644 index 000000000..447c91981 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUU b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUU new file mode 100644 index 000000000..083c30039 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/FUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUF b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUF new file mode 100644 index 000000000..ef36a432d --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUF @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUT b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUT new file mode 100644 index 000000000..05f65ad45 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUT @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUU b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUU new file mode 100644 index 000000000..d6e54b326 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/TUU @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUF b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUF new file mode 100644 index 000000000..5f69fb73f --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUF @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUT b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUT new file mode 100644 index 000000000..d7ef8cd88 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUT @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUU b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUU new file mode 100644 index 000000000..005a4f462 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/OrIntroductionDirectRule/UUU @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/shorttruthtable/rules/TrueOrFalseCaseRule/Statement b/src/test/resources/puzzles/shorttruthtable/rules/TrueOrFalseCaseRule/Statement new file mode 100644 index 000000000..51a9d8b39 --- /dev/null +++ b/src/test/resources/puzzles/shorttruthtable/rules/TrueOrFalseCaseRule/Statement @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFail b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFail new file mode 100644 index 000000000..f826667e3 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFail @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom new file mode 100644 index 000000000..80deadaea --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft new file mode 100644 index 000000000..d19e01daf --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight new file mode 100644 index 000000000..bf3954964 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailTop b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailTop new file mode 100644 index 000000000..8eaa974ea --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailTop @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent new file mode 100644 index 000000000..daba3648e --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FailTent b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FailTent new file mode 100644 index 000000000..9fa14ebe4 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FailTent @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrass b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrassJustRow similarity index 100% rename from src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrass rename to src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrassJustRow diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrassJustTent b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrassJustTent new file mode 100644 index 000000000..cbd3662e6 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/FinishWithGrassJustTent @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/MiddleTent b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/MiddleTent new file mode 100644 index 000000000..8f71a57f9 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/MiddleTent @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/NoTent b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/NoTent new file mode 100644 index 000000000..a13c7cc55 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/NoTent @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/SpacedOutTent b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/SpacedOutTent new file mode 100644 index 000000000..f7b523b0a --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithGrassDirectRule/SpacedOutTent @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/AdditionalTents b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/AdditionalTents new file mode 100644 index 000000000..6fea9f102 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/AdditionalTents @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/AmbiguousTents b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/AmbiguousTents new file mode 100644 index 000000000..96f2ed729 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/AmbiguousTents @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithHorizontalTents b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithHorizontalTents new file mode 100644 index 000000000..a10c04124 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithHorizontalTents @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTents b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTents index a10c04124..a292cc972 100644 --- a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTents +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTents @@ -2,16 +2,16 @@ - + - - + + - + diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsBothWays b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsBothWays new file mode 100644 index 000000000..c4d58ef60 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsBothWays @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsFail b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsFail new file mode 100644 index 000000000..a13c7cc55 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsFail @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithVerticalTents b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithVerticalTents new file mode 100644 index 000000000..0a340cd17 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithVerticalTents @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/TooManyTents b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/TooManyTents new file mode 100644 index 000000000..8f71a57f9 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FinishWithTentsDirectRule/TooManyTents @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotDown b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotDown new file mode 100644 index 000000000..cb19ab33f --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotDown @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotLeft b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotLeft new file mode 100644 index 000000000..e70dc4be5 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotLeft @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotRight b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotRight new file mode 100644 index 000000000..64ddf29db --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotRight @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpot b/src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotUp similarity index 100% rename from src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpot rename to src/test/resources/puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotUp diff --git a/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeDiagonal b/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeDiagonal new file mode 100644 index 000000000..af0b49e31 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeDiagonal @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTrees b/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTrees new file mode 100644 index 000000000..5111e0585 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTrees @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTreesDiagonal b/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTreesDiagonal new file mode 100644 index 000000000..10391b85c --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTentForTreeContradictionRule/NoTentForTreeTwoTreesDiagonal @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent3x3 b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent3x3 new file mode 100644 index 000000000..9c5e81936 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent3x3 @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentDiagonals b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentDiagonals new file mode 100644 index 000000000..ad086bbc1 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentDiagonals @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentJustTent b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentJustTent new file mode 100644 index 000000000..93aaf451f --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentJustTent @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNE b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNE new file mode 100644 index 000000000..80ffb9525 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNE @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNW similarity index 100% rename from src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTent rename to src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentNW diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSE b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSE new file mode 100644 index 000000000..c2fc5206d --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSE @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSW b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSW new file mode 100644 index 000000000..8e8249b27 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentSW @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentYesTree b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentYesTree new file mode 100644 index 000000000..f46e4b5a5 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/NoTreeForTentContradictionRule/NoTreeForTentYesTree @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassBad b/src/test/resources/puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassBad new file mode 100644 index 000000000..6065d42cd --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassBad @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassTrees b/src/test/resources/puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassTrees new file mode 100644 index 000000000..e8fef64dc --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassTrees @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TentOrGrassCaseRule/TentOrGrassTest b/src/test/resources/puzzles/treetent/rules/TentOrGrassCaseRule/TentOrGrassTest new file mode 100644 index 000000000..9ae8455e1 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TentOrGrassCaseRule/TentOrGrassTest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TentOrGrassCaseRule/TestPuzzle b/src/test/resources/puzzles/treetent/rules/TentOrGrassCaseRule/TestPuzzle new file mode 100644 index 000000000..a13c7cc55 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TentOrGrassCaseRule/TestPuzzle @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Column b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Column new file mode 100644 index 000000000..0f78702c4 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Column @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Row b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Row new file mode 100644 index 000000000..c423b179b --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents2x2Row @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3Column b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3Column new file mode 100644 index 000000000..d1e79a76e --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3Column @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3DoubleColumn b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3DoubleColumn new file mode 100644 index 000000000..e71832f08 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents3x3DoubleColumn @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsDoubleBad b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsDoubleBad new file mode 100644 index 000000000..ecc8988c6 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsDoubleBad @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsJustY similarity index 100% rename from src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTents rename to src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsJustY diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsNoContradiction b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsNoContradiction new file mode 100644 index 000000000..2f609e161 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsNoContradiction @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsWithTent b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsWithTent new file mode 100644 index 000000000..8ae51f0a3 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooFewTentsContradictionRule/TooFewTentsWithTent @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomAccount b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomAccount new file mode 100644 index 000000000..8474e916a --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomAccount @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsContradictionRuleColumn_Row b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomDown similarity index 93% rename from src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsContradictionRuleColumn_Row rename to src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomDown index 78e956c35..8051a5501 100644 --- a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsContradictionRuleColumn_Row +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomDown @@ -8,7 +8,7 @@ - + diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomMissDown b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomMissDown new file mode 100644 index 000000000..3cbb1cdb4 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomMissDown @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomMissRight b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomMissRight new file mode 100644 index 000000000..d22778c4e --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomMissRight @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomRight b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomRight new file mode 100644 index 000000000..aeb4cd148 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsBottomRight @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopAccount b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopAccount new file mode 100644 index 000000000..258e32d47 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopAccount @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopDown b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopDown new file mode 100644 index 000000000..58d4bbddf --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopDown @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopRight b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopRight new file mode 100644 index 000000000..dd5b7b935 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTopRight @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTotalFail b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTotalFail new file mode 100644 index 000000000..9fbb8b82f --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TooManyTentsContradictionRule/TooManyTentsTotalFail @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsAdjacentAlt b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsAdjacentAlt new file mode 100644 index 000000000..902fb3ee7 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsAdjacentAlt @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsDiagonalAlt b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsDiagonalAlt new file mode 100644 index 000000000..9b35fb998 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsDiagonalAlt @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsFull2By2 b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsFull2By2 new file mode 100644 index 000000000..59805ca35 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsFull2By2 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft new file mode 100644 index 000000000..af4ca0831 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownRight b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownRight new file mode 100644 index 000000000..05b7a7667 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownRight @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpLeft b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpLeft new file mode 100644 index 000000000..b8b81c7b4 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpLeft @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpRight b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpRight new file mode 100644 index 000000000..af7fb5df2 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpRight @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeAdjacent b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeAdjacent new file mode 100644 index 000000000..4c63558c2 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeAdjacent @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeDiagonal b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeDiagonal new file mode 100644 index 000000000..b2f54aef3 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeDiagonal @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file