From 8b2397ab1abbd3ffe203406d7a6bad0995254913 Mon Sep 17 00:00:00 2001 From: Jaden Tian <56417002+jadeandtea@users.noreply.github.com> Date: Sun, 5 May 2024 13:38:18 -0400 Subject: [PATCH 1/3] Tree Tent Test Suite (#775) * TentForTree test cases One valid case of connecting a tree to a tent One invalid case of connecting a tree to a tent when there is another valid tent * Incomplete test for already connected tree * Test for Fill in Row Case Rule Looks like the case rule was implemented incorrectly :/ * Fill in Row Test Cases Actually case generator works properly * Fill in Row Test Cases When the clue is that there are 0 tents, the case returned should be equivalent to FinishWithGrass. * Comments * Fix TreeTent Puzzle Editor * LinkTentCaseRule Four Trees Test Case Expected to create four cases, each one connecting a line between the tree in the center and one of the four surrounding trees. * LinkTentCaseRule Various Test Cases With one tree, one case is created. With no trees, no cases are created. With diagonal trees, no cases are created. * TreeTent Puzzle Editor Fix Removed double-calling setCell due to custom and super mouseReleased * LinkTreeCaseRule Test Cases Similar test cases to LinkTentCaseRule - Make sure diagonal tents have no bearing on cases - Make sure no tents around the tree fails - One tent should connect to the correct tree - Two tents should create two cases - No other cases to check, as there cannot be more than two tents around a tree; otherwise, the tents would touch * Reset puzzle * Improved FillInRowCaseRule Rewrote recursive generate board function to be slightly more optimized * Fix FillInRowCaseRule * Implement Copy Clue function Fixes a bug where you couldn't apply the FillInRow Case Rule on a child node * Allow Importing Puzzle-Specific Puzzle Elements When checking the proof tree, the Puzzle Importer only checks for changed cells. However, for TreeTent, the user can create lines, which cannot be saved as a "cell" object. Now, an importer class can override the getImporterElements function to specify what types of changes the board may experience. * Fix Puzzles Uneven Sides Simple mistake in calculation of index * Check Rule on Columns Adjust all simple cases to also check the central column rule * Change test puzzle names * FillInRowCaseRule Test Checks that the rule works on an empty 5x5 board * TreeForTent tests and TentForTree tests * Minor formatting changes * Fix boards with uneven side lengths * Comments * Standardizing Comments * Standardizing Comments All Direct Rules * Fix Build Issues The Ubuntu and Checkstyle Autocompilers have trouble opening this file for some reason * Comment out problematic file * Uncommenting problematic test * Update file name * Commented out Star Battle test --------- Co-authored-by: Charles Tian <46334090+charlestian23@users.noreply.github.com> Co-authored-by: charlestian23 --- .../treetent/8x8 TreeTent Easy/1646651 | 5 +- .../edu/rpi/legup/model/PuzzleImporter.java | 18 +- .../legup/puzzle/treetent/TreeTentBoard.java | 46 +- .../puzzle/treetent/TreeTentCellFactory.java | 2 +- .../legup/puzzle/treetent/TreeTentClue.java | 2 +- .../puzzle/treetent/TreeTentController.java | 8 +- .../puzzle/treetent/TreeTentExporter.java | 2 +- .../puzzle/treetent/TreeTentImporter.java | 13 +- .../treetent/rules/FillinRowCaseRule.java | 106 ++-- .../rules/BlackoutDirectRuleTest.java | 140 +++--- .../rules/EmptyFieldDirectRuleTest.java | 169 ++----- .../treetent/rules/FillinRowCaseRuleTest.java | 464 ++++++++++++++++++ .../rules/FinishWithGrassDirectRuleTest.java | 136 +++-- .../rules/FinishWithTentsDirectRuleTest.java | 143 +++--- .../rules/LastCampingSpotDirectRuleTest.java | 72 +-- .../treetent/rules/LinkTentCaseRuleTest.java | 191 +++++++ .../treetent/rules/LinkTreeCaseRuleTest.java | 192 ++++++++ .../SurroundTentWithGrassDirectRuleTest.java | 54 +- .../rules/TentForTreeDirectRuleTest.java | 171 ++++++- .../TooManyTentsContradictionRuleTest.java | 2 +- .../TouchingTentsContradictionRuleTest.java | 86 +--- .../rules/TreeForTentDirectRuleTest.java | 163 +++++- .../EmptyRow3x3OneTent} | 5 +- .../EmptyRow3x3ThreeTent} | 5 +- .../EmptyRow3x3TwoTent} | 11 +- .../EmptyRow3x3ZeroTent} | 1 - .../FillinRowCaseRule/EmptyRow5x5TwoTent | 23 + .../FillinRowCaseRule/PartialFillOneTent | 29 ++ .../treetent/rules/LinkTentCaseRule/DiagTrees | 26 + .../rules/LinkTentCaseRule/FourTreesOneTent | 26 + .../treetent/rules/LinkTentCaseRule/NoTrees | 22 + .../rules/LinkTentCaseRule/OneTreeOneTent | 23 + .../treetent/rules/LinkTreeCaseRule/DiagTents | 26 + .../treetent/rules/LinkTreeCaseRule/NoTents | 22 + .../treetent/rules/LinkTreeCaseRule/OneTent | 23 + .../treetent/rules/LinkTreeCaseRule/TwoTents | 24 + .../rules/TentForTreeDirectRule/ArbitraryTree | 28 ++ .../rules/TentForTreeDirectRule/ConnectedTent | 31 ++ .../TentForTreeDirectRule/OneTreeOneTent | 28 ++ .../OneTreeTwoAdjacentTent | 28 ++ .../TouchingTentsMixedDownRight | 20 - .../TouchingTentsMixedUpLeft | 20 - .../TouchingTentsMixedUpRight | 20 - .../TouchingTentsTreeDiagonal | 2 +- .../rules/TreeForTentDirectRule/ArbitraryTent | 28 ++ .../rules/TreeForTentDirectRule/ConnectedTree | 31 ++ .../TreeForTentDirectRule/OneTentOneTree | 28 ++ .../OneTentTwoAdjacentTrees | 28 ++ 48 files changed, 2155 insertions(+), 588 deletions(-) create mode 100644 src/test/java/puzzles/treetent/rules/FillinRowCaseRuleTest.java create mode 100644 src/test/java/puzzles/treetent/rules/LinkTentCaseRuleTest.java create mode 100644 src/test/java/puzzles/treetent/rules/LinkTreeCaseRuleTest.java rename src/test/resources/puzzles/treetent/rules/{EmptyFieldDirectRule/EmptyFieldFailLeft => FillinRowCaseRule/EmptyRow3x3OneTent} (78%) rename src/test/resources/puzzles/treetent/rules/{EmptyFieldDirectRule/EmptyFieldFailRight => FillinRowCaseRule/EmptyRow3x3ThreeTent} (78%) rename src/test/resources/puzzles/treetent/rules/{TouchingTentsContradictionRule/TouchingTentsMixedDownLeft => FillinRowCaseRule/EmptyRow3x3TwoTent} (57%) rename src/test/resources/puzzles/treetent/rules/{EmptyFieldDirectRule/EmptyFieldFailBottom => FillinRowCaseRule/EmptyRow3x3ZeroTent} (92%) create mode 100644 src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow5x5TwoTent create mode 100644 src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/PartialFillOneTent create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/DiagTrees create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/FourTreesOneTent create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/NoTrees create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/OneTreeOneTent create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/DiagTents create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/NoTents create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/OneTent create mode 100644 src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/TwoTents create mode 100644 src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ArbitraryTree create mode 100644 src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ConnectedTent create mode 100644 src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeOneTent create mode 100644 src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeTwoAdjacentTent delete mode 100644 src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownRight delete mode 100644 src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpLeft delete mode 100644 src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpRight create mode 100644 src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ArbitraryTent create mode 100644 src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ConnectedTree create mode 100644 src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentOneTree create mode 100644 src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentTwoAdjacentTrees diff --git a/puzzles files/treetent/8x8 TreeTent Easy/1646651 b/puzzles files/treetent/8x8 TreeTent Easy/1646651 index 36dbc7f1e..db70ca164 100644 --- a/puzzles files/treetent/8x8 TreeTent Easy/1646651 +++ b/puzzles files/treetent/8x8 TreeTent Easy/1646651 @@ -1,5 +1,6 @@ - + + @@ -38,5 +39,5 @@ - + diff --git a/src/main/java/edu/rpi/legup/model/PuzzleImporter.java b/src/main/java/edu/rpi/legup/model/PuzzleImporter.java index 0cc163200..c22831c8d 100644 --- a/src/main/java/edu/rpi/legup/model/PuzzleImporter.java +++ b/src/main/java/edu/rpi/legup/model/PuzzleImporter.java @@ -6,6 +6,8 @@ import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.tree.*; import edu.rpi.legup.save.InvalidFileFormatException; + +import java.lang.reflect.Array; import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -130,6 +132,19 @@ public void initializePuzzle(Node node) throws InvalidFileFormatException { public abstract void initializeBoard(String[] statements) throws UnsupportedOperationException, IllegalArgumentException; + /** + * Used to check that elements in the proof tree are saved properly. + *

Make sure the list elements are lowercase + * + * @return A list of elements that will change when solving the puzzle + * * e.g. {"cell"}, {"cell", "line"} + */ + public List getImporterElements() { + List elements = new ArrayList<>(); + elements.add("cell"); + return elements; + } + /** * Creates the proof for building * @@ -379,7 +394,8 @@ protected void makeTransitionChanges(TreeTransition transition, Node transElemen NodeList cellList = transElement.getChildNodes(); for (int i = 0; i < cellList.getLength(); i++) { Node node = cellList.item(i); - if (node.getNodeName().equalsIgnoreCase("cell")) { + List elements = getImporterElements(); + if (elements.contains(node.getNodeName().toLowerCase())) { Board board = transition.getBoard(); PuzzleElement cell = puzzle.getFactory().importCell(node, board); 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 09706f92a..6ded23a18 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java @@ -3,6 +3,8 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.GridBoard; import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.tree.Tree; + import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -53,21 +55,29 @@ public TreeTentCell getCell(int x, int y) { @Override public PuzzleElement getPuzzleElement(PuzzleElement element) { - switch (element.getIndex()) { - case -2: - return element; - case -1: - TreeTentLine line = (TreeTentLine) element; - TreeTentLine thisLine = null; - for (TreeTentLine l : lines) { - if (line.compare(l)) { - thisLine = l; - break; - } - } - return thisLine; - default: - return super.getPuzzleElement(element); + return switch (element.getIndex()) { + case -2 -> element; + case -1 -> element; + default -> super.getPuzzleElement(element); + }; + } + + @Override + public void setPuzzleElement(int index, PuzzleElement puzzleElement) { + if (index == -1) { + lines.add((TreeTentLine) puzzleElement); + } else if (index < puzzleElements.size()) { + puzzleElements.set(index, puzzleElement); + } + } + + @Override + public void notifyChange(PuzzleElement puzzleElement) { + int index = puzzleElement.getIndex(); + if (index == -1) { + lines.add((TreeTentLine) puzzleElement); + } else if (index < puzzleElements.size()) { + puzzleElements.set(index, puzzleElement); } } @@ -168,20 +178,20 @@ public List getDiagonals(TreeTentCell cell, TreeTentType type) { * * @param index the row or column number * @param type type of TreeTent element - * @param isRow boolean value beased on whether a row of column is being checked + * @param isRow boolean value based on whether a row of column is being checked * @return List of TreeTentCells that match the given TreeTentType */ public List getRowCol(int index, TreeTentType type, boolean isRow) { List list = new ArrayList<>(); if (isRow) { - for (int i = 0; i < dimension.height; i++) { + for (int i = 0; i < dimension.width; i++) { TreeTentCell cell = getCell(i, index); if (cell.getType() == type) { list.add(cell); } } } else { - for (int i = 0; i < dimension.width; i++) { + for (int i = 0; i < dimension.height; i++) { TreeTentCell cell = getCell(index, i); if (cell.getType() == type) { list.add(cell); 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 1697b8bd5..a3553940d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCellFactory.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentCellFactory.java @@ -39,7 +39,7 @@ public PuzzleElement importCell(Node node, Board board) throws InvalidFileFormat } TreeTentCell cell = new TreeTentCell(TreeTentType.valueOf(value), new Point(x, y)); - cell.setIndex(y * height + x); + cell.setIndex(y * width + x); return cell; } else { if (node.getNodeName().equalsIgnoreCase("line")) { diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentClue.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentClue.java index bcba7dc94..7b93f1301 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentClue.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentClue.java @@ -50,6 +50,6 @@ public void setType(TreeTentType type) { } public TreeTentClue copy() { - return null; + return new TreeTentClue(data, clueIndex, type); } } 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 79e074657..667c2ba7d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentController.java @@ -32,8 +32,10 @@ public TreeTentController() { 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()); + if (boardView != null) { + dragStart = boardView.getElement(e.getPoint()); + lastCellPressed = boardView.getElement(e.getPoint()); + } } } @@ -105,6 +107,8 @@ public void mouseReleased(MouseEvent e) { } dragStart = null; lastCellPressed = null; + } else { + super.mouseReleased(e); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentExporter.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentExporter.java index 475aaab1e..82c1b373d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentExporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentExporter.java @@ -52,7 +52,7 @@ protected org.w3c.dom.Element createBoardElement(Document newDocument) { org.w3c.dom.Element axisSouth = newDocument.createElement("axis"); axisSouth.setAttribute("side", "south"); - for (TreeTentClue clue : board.getRowClues()) { + for (TreeTentClue clue : board.getColClues()) { org.w3c.dom.Element clueElement = newDocument.createElement("clue"); clueElement.setAttribute("value", String.valueOf(clue.getData())); clueElement.setAttribute("index", String.valueOf(clue.getClueIndex())); diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java index 0117f41ce..c791617ce 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java @@ -3,6 +3,9 @@ import edu.rpi.legup.model.PuzzleImporter; import edu.rpi.legup.save.InvalidFileFormatException; import java.awt.*; +import java.util.ArrayList; +import java.util.List; + import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -113,7 +116,7 @@ public void initializeBoard(Node node) throws InvalidFileFormatException { for (int x = 0; x < width; x++) { if (treeTentBoard.getCell(x, y) == null) { TreeTentCell cell = new TreeTentCell(TreeTentType.UNKNOWN, new Point(x, y)); - cell.setIndex(y * height + x); + cell.setIndex(y * width + x); cell.setModifiable(true); treeTentBoard.setCell(x, y, cell); } @@ -216,4 +219,12 @@ public void initializeBoard(Node node) throws InvalidFileFormatException { public void initializeBoard(String[] statements) throws UnsupportedOperationException { throw new UnsupportedOperationException("Tree Tent cannot accept text input"); } + + @Override + public List getImporterElements() { + List elements = new ArrayList<>(); + elements.add("cell"); + elements.add("line"); + return elements; + } } 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 0116c0dcd..a796c992a 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 @@ -1,9 +1,11 @@ package edu.rpi.legup.puzzle.treetent.rules; +import edu.rpi.legup.model.Puzzle; 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.Tree; import edu.rpi.legup.model.tree.TreeTransition; import edu.rpi.legup.puzzle.treetent.TreeTentBoard; import edu.rpi.legup.puzzle.treetent.TreeTentCell; @@ -11,7 +13,9 @@ import edu.rpi.legup.puzzle.treetent.TreeTentType; import java.awt.*; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.ListIterator; public class FillinRowCaseRule extends CaseRule { @@ -61,7 +65,7 @@ public CaseBoard getCaseBoard(Board board) { */ @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { - ArrayList cases = new ArrayList(); + ArrayList cases; List group; int tentsLeft; TreeTentClue clue = ((TreeTentClue) puzzleElement); @@ -70,7 +74,7 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { if (clue.getType() == TreeTentType.CLUE_SOUTH) { group = tBoard.getRowCol(clueIndex, TreeTentType.UNKNOWN, false); tentsLeft = - tBoard.getRowClues().get(clueIndex).getData() + tBoard.getColClues().get(clueIndex).getData() - tBoard.getRowCol(clueIndex, TreeTentType.TENT, false).size(); cases = genCombinations(tBoard, group, tentsLeft, clueIndex, false); } else { @@ -83,60 +87,100 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { // generate every combination (nCr) // call goodBoard for each generated combination - // alternitive would be to implement collision avoidance while generating instead of after + // alternative would be to implement collision avoidance while generating instead of after if (cases.size() > 0) { return cases; } return null; } + /** + * + * @param iBoard the board to place tents onto + * @param tiles the locations where tents can be placed + * @param target the target number of tents to place + * @param index the index of tiles which is trying to be placed + * @param isRow Used to check validity of board + * @return the list of boards created + */ private ArrayList genCombinations( TreeTentBoard iBoard, List tiles, int target, Integer index, boolean isRow) { - return genCombRecursive( - iBoard, tiles, tiles, target, 0, new ArrayList(), index, isRow); + ArrayList generatedBoards = new ArrayList<>(); + genCombRecursive( + iBoard, tiles, target, 0, new ArrayList(), 0, index, generatedBoards, isRow); + return generatedBoards; } - private ArrayList genCombRecursive( + /** + * + * Recursive function to generate all ways of placing the target number of tents + * from the list of tiles to fill. + * + * @param iBoard The board + * @param tiles Unknown Tiles to fill + * @param target number of tents to place + * @param current number of tents already placed + * @param currentTile index of the next tile to add + * @param selected the cells which have tents + * @param index The index of the clue + * @param isRow Used for checking if the board is good + * + * The generated boards are placed into generatedBoards (passed by reference) + */ + + private void genCombRecursive( TreeTentBoard iBoard, - List original, List tiles, int target, int current, List selected, + int currentTile, Integer index, + ArrayList generatedBoards, boolean isRow) { - ArrayList b = new ArrayList<>(); + // Base Case: Enough tents have been placed if (target == current) { - TreeTentBoard temp = iBoard.copy(); - for (TreeTentCell c : original) { - if (selected.contains(c)) { - PuzzleElement change = temp.getPuzzleElement(c); - change.setData(TreeTentType.TENT); - temp.addModifiedData(change); - } else { - PuzzleElement change = temp.getPuzzleElement(c); - change.setData(TreeTentType.GRASS); - temp.addModifiedData(change); + TreeTentBoard boardCopy = iBoard.copy(); + // Selected Tiles should already be filled + // Fill in other tiles with Grass + for (TreeTentCell tile : tiles) { + if (!selected.contains(tile)) { + PuzzleElement element = boardCopy.getPuzzleElement(tile); + element.setData(TreeTentType.GRASS); + boardCopy.addModifiedData(element); } } - if (goodBoard(temp, index, isRow)) { - b.add(temp); - } - return b; + // board validity is checked after placing every tent + // because the base case doesn't place any tents, the board + // should still be valid + generatedBoards.add(boardCopy); + return; } - for (int i = 0; i < tiles.size(); ++i) { - List sub = tiles.subList(i + 1, tiles.size()); - List next = new ArrayList(selected); - next.add(tiles.get(i)); - b.addAll( - genCombRecursive( - iBoard, original, sub, target, current + 1, next, index, isRow)); + + // Recursive Case: + // Looking at the group of possible tiles, save one of the tiles into selected, + // Place it on the board, + // Check if the board is good and recurse + // + // Backtracking: + // Remove the placed tent from the board and selected + for (int i = currentTile; i < tiles.size(); ++i){ + TreeTentCell tile = tiles.get(i); + selected.add(tile); + PuzzleElement element = iBoard.getPuzzleElement(tile); + element.setData(TreeTentType.TENT); + iBoard.addModifiedData(element); + if (goodBoard(iBoard, index, isRow)) { + genCombRecursive(iBoard, tiles, target, current + 1, selected, i + 1, index, generatedBoards, isRow); + } + element.setData(TreeTentType.UNKNOWN); + iBoard.addModifiedData(element); + selected.remove(tile); } - return b; } // Effectively runs TouchingTents check on all the added tents to make sure that the proposed @@ -153,7 +197,7 @@ private boolean goodBoard(TreeTentBoard board, Integer index, boolean isRow) { for (TreeTentCell t : tents) { List adj = board.getAdjacent(t, TreeTentType.TENT); List diag = board.getDiagonals(t, TreeTentType.TENT); - if (adj.size() > 0 || diag.size() > 0) { + if (!adj.isEmpty() || !diag.isEmpty()) { return false; } } diff --git a/src/test/java/puzzles/starbattle/rules/BlackoutDirectRuleTest.java b/src/test/java/puzzles/starbattle/rules/BlackoutDirectRuleTest.java index d42f40c87..7789b273b 100644 --- a/src/test/java/puzzles/starbattle/rules/BlackoutDirectRuleTest.java +++ b/src/test/java/puzzles/starbattle/rules/BlackoutDirectRuleTest.java @@ -1,69 +1,73 @@ -package puzzles.starbattle.rules; +// This test is for a puzzle that is not fully implemented yet and is causing issues. +// Commenting this out for now, but once Star Battle is fully implemented this should +// be uncommented and finished. -import edu.rpi.legup.puzzle.nurikabe.Nurikabe; -import edu.rpi.legup.puzzle.nurikabe.NurikabeBoard; -import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; -import edu.rpi.legup.puzzle.nurikabe.NurikabeType; -import legup.MockGameBoardFacade; -import legup.TestUtilities; -import edu.rpi.legup.model.tree.TreeNode; -import edu.rpi.legup.model.tree.TreeTransition; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import edu.rpi.legup.puzzle.starbattle.StarBattle; -import edu.rpi.legup.puzzle.starbattle.StarBattleBoard; -import edu.rpi.legup.puzzle.starbattle.StarBattleCell; -import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; -import edu.rpi.legup.puzzle.starbattle.rules.BlackoutDirectRule; -import edu.rpi.legup.save.InvalidFileFormatException; - -import java.awt.*; - -public class BlackoutDirectRuleTest { - - private static final BlackoutDirectRule RULE = new BlackoutDirectRule(); - private static StarBattle starbattle; - - @BeforeClass - public static void setUp() { - MockGameBoardFacade.getInstance(); - starbattle = new StarBattle(); - } - - @Test - public void BlackoutDirectRuleTest_ColumnBlackout() throws InvalidFileFormatException { - TestUtilities.importTestBoard("puzzles/starbattle/rules/BlackoutDirectRule/ColumnBlackout", starbattle); - TreeNode rootNode = starbattle.getTree().getRootNode(); - TreeTransition transition = rootNode.getChildren().get(0); - transition.setRule(RULE); - - StarBattleBoard board = (StarBattleBoard) transition.getBoard(); - - StarBattleCell cell1 = board.getCell(1, 1); - cell1.setData(StarBattleCellType.BLACK.value); - StarBattleCell cell2 = board.getCell(1, 2); - cell2.setData(StarBattleCellType.BLACK.value); - StarBattleCell cell3 = board.getCell(1, 3); - cell3.setData(StarBattleCellType.BLACK.value); - - board.addModifiedData(cell1); - board.addModifiedData(cell2); - board.addModifiedData(cell3); - - 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())) { - Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i))); - } - else { - Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i))); - } - } - } - } -} +//package puzzles.starbattle.rules; +// +//import edu.rpi.legup.puzzle.nurikabe.Nurikabe; +//import edu.rpi.legup.puzzle.nurikabe.NurikabeBoard; +//import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; +//import edu.rpi.legup.puzzle.nurikabe.NurikabeType; +//import legup.MockGameBoardFacade; +//import legup.TestUtilities; +//import edu.rpi.legup.model.tree.TreeNode; +//import edu.rpi.legup.model.tree.TreeTransition; +//import org.junit.Assert; +//import org.junit.BeforeClass; +//import org.junit.Test; +// +//import edu.rpi.legup.puzzle.starbattle.StarBattle; +//import edu.rpi.legup.puzzle.starbattle.StarBattleBoard; +//import edu.rpi.legup.puzzle.starbattle.StarBattleCell; +//import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; +//import edu.rpi.legup.puzzle.starbattle.rules.BlackoutDirectRule; +//import edu.rpi.legup.save.InvalidFileFormatException; +// +//import java.awt.*; +// +//public class BlackoutDirectRuleTest { +// +// private static final BlackoutDirectRule RULE = new BlackoutDirectRule(); +// private static StarBattle starbattle; +// +// @BeforeClass +// public static void setUp() { +// MockGameBoardFacade.getInstance(); +// starbattle = new StarBattle(); +// } +// +// @Test +// public void BlackoutDirectRuleTest_ColumnBlackout() throws InvalidFileFormatException { +// TestUtilities.importTestBoard("puzzles/starbattle/rules/BlackoutDirectRule/ColumnBlackout", starbattle); +// TreeNode rootNode = starbattle.getTree().getRootNode(); +// TreeTransition transition = rootNode.getChildren().get(0); +// transition.setRule(RULE); +// +// StarBattleBoard board = (StarBattleBoard) transition.getBoard(); +// +// StarBattleCell cell1 = board.getCell(1, 1); +// cell1.setData(StarBattleCellType.BLACK.value); +// StarBattleCell cell2 = board.getCell(1, 2); +// cell2.setData(StarBattleCellType.BLACK.value); +// StarBattleCell cell3 = board.getCell(1, 3); +// cell3.setData(StarBattleCellType.BLACK.value); +// +// board.addModifiedData(cell1); +// board.addModifiedData(cell2); +// board.addModifiedData(cell3); +// +// 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())) { +// 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/EmptyFieldDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java index 38284c410..8ffb2ee4f 100644 --- a/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/EmptyFieldDirectRuleTest.java @@ -26,11 +26,17 @@ 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 { + /** + * 3x3 TreeTent puzzle Tests EmptyFieldDirectRule + *

Empty + * XXX + * XGX + * XXX + *

Makes the (1, 1) tile GRASS + * Checks if the rule correctly detects no trees around the grass tile + */ + @Test + public void EmptyFieldTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/EmptyFieldDirectRule/EmptyField", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -64,12 +70,17 @@ public void EmptyFieldTest() throws InvalidFileFormatException { } } - // 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 { + /** + * 3x3 TreeTent puzzle Tests EmptyFieldDirectRule + *

Trees are at (0, 0), (2, 0), (0, 2), and (2, 2) + * RXR + * XGX + * RXR + *

Makes the (1, 1) tile GRASS + * Checks if the rule correctly ignores the trees on the diagonals + */ + @Test + public void DiagonalTreeTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/EmptyFieldDirectRule/DiagonalTree", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -103,12 +114,17 @@ public void DiagonalTreeTest() throws InvalidFileFormatException { } } - // 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 { + /** + * 3x3 TreeTent puzzle Tests EmptyFieldDirectRule + *

Trees are at (0, 1), (1, 0), (1, 2), and (2, 1) + * XRX + * RGR + * XRX + *

Makes the (1, 1) tile GRASS + * Checks if the rule is not valid when there are adjacent trees + */ + @Test + public void EmptyFieldTestFail() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFail", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -137,12 +153,17 @@ public void EmptyFieldTestFail() throws InvalidFileFormatException { } } - // 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 { + /** + * 3x3 TreeTent puzzle Tests EmptyFieldDirectRule + *

Tree at (1, 0) + * XRX + * XGX + * XXX + *

Makes the (1, 1) tile GRASS + * Checks if the rule is not valid when there is one adjacent tree + */ + @Test + public void EmptyFieldTestFailTop() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailTop", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -170,106 +191,4 @@ public void EmptyFieldTestFailTop() throws InvalidFileFormatException { } } } - - // 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/FillinRowCaseRuleTest.java b/src/test/java/puzzles/treetent/rules/FillinRowCaseRuleTest.java new file mode 100644 index 000000000..71b478e7a --- /dev/null +++ b/src/test/java/puzzles/treetent/rules/FillinRowCaseRuleTest.java @@ -0,0 +1,464 @@ +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.*; +import edu.rpi.legup.puzzle.treetent.rules.FillinRowCaseRule; +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.lang.reflect.Array; +import java.util.ArrayList; + +public class FillinRowCaseRuleTest { + private static final FillinRowCaseRule RULE = new FillinRowCaseRule(); + private static TreeTent treetent; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + treetent = new TreeTent(); + } + + /** + * empty 3x3 TreeTent puzzle Tests FillinRowCaseRule on row with 3 UNKNOWN tiles + * and a clue of 0 tents in the row. + * + *

checks that 1 case is created and that it is equivalent to FinishWithGrass rule + * May need to change checks due to issue #777 + * + * @throws InvalidFileFormatException + */ + @Test + public void TentOrTreeTestZeroTentClue() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ZeroTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + /* Test the Row */ + TreeTentClue testing_row = board.getClue(3, 1); + ArrayList cases = RULE.getCases(board, testing_row); + + // assert that one case was found + Assert.assertEquals(1, cases.size()); + + // assert the case filled the row with grass + TreeTentBoard testCase = (TreeTentBoard) cases.getFirst(); + Assert.assertEquals(3, testCase.getRowCol(1, TreeTentType.GRASS, true).size()); + + // 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 (h == 1) { + continue; + } + + original_cell = board.getCell(w, h); + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + + /* Test the Column */ + TreeTentClue testing_col = board.getClue(1, 3); + cases = RULE.getCases(board, testing_col); + + // assert one case was created + Assert.assertEquals(1, cases.size()); + + // assert the case filled the column with grass + testCase = (TreeTentBoard) cases.getFirst(); + Assert.assertEquals(3, testCase.getRowCol(1, TreeTentType.GRASS, false).size()); + + // checks other cells have not been modified + for (int w = 0; w < board.getWidth(); w++) { + for (int h = 0; h < board.getHeight(); h++) { + if (w == 1) { + continue; + } + + original_cell = board.getCell(w, h); + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests FillinRowCaseRule on row with 3 UNKNOWN tiles + * and a clue of 1 tent in the row. The column rules make the board impossible, but + * they are not checked here. + * + *

checks 3 cases are created checks; + * first case is TENT tile at x=0, + * second case is TENT tile at x=1, + * and a third case is TENT tile at x=2. + * The cases can be in any order. + * Then, it checks that other cells have not been modified + * + * @throws InvalidFileFormatException + */ + @Test + public void FillInRowEmptyOneTentClue() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3OneTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + /* Test the Row */ + TreeTentClue testing_row = board.getClue(3, 1); + ArrayList cases = RULE.getCases(board, testing_row); + + // assert correct number of cases created + Assert.assertEquals(3, cases.size()); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + // Each case must have 1 tent in the row + Assert.assertEquals(1, testCase.getRowCol(1, TreeTentType.TENT, true).size()); + + // and they must have 2 grass tiles in the row + Assert.assertEquals(2, testCase.getRowCol(1, TreeTentType.GRASS, true).size()); + } + + // 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 (h == 1) { + continue; + } + + original_cell = board.getCell(w, h); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + + } + } + } + + /* Test the Column */ + TreeTentClue testing_col = board.getClue(1, 3); + cases = RULE.getCases(board, testing_col); + + // assert correct number of cases created + Assert.assertEquals(3, cases.size()); + // Only one arrangement is possible when taking into account the + // touching tents contradiction rule. + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + // Each case must have 1 tent in the column + Assert.assertEquals(1, testCase.getRowCol(1, TreeTentType.TENT, false).size()); + + // and they must have 2 grass tiles in the column + Assert.assertEquals(2, testCase.getRowCol(1, TreeTentType.GRASS, false).size()); + } + + // checks other cells have not been modified + for (int w = 0; w < board.getWidth(); w++) { + for (int h = 0; h < board.getHeight(); h++) { + if (w == 1) { + continue; + } + + original_cell = board.getCell(w, h); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests FillinRowCaseRule on row with 3 UNKNOWN tiles + * and a clue of 2 tent in the row. The column rules make the board impossible, but + * they are not checked here. + * + *

checks 1 case is created. Checks that the case is when + * there are TENT tiles at x=0 and x=2. + * Then, it checks that other cells have not been modified + * + * @throws InvalidFileFormatException + */ + @Test + public void FillInRowEmptyTwoTentClue() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3TwoTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + /* Test the Row */ + TreeTentClue testing_row = board.getClue(3, 1); + ArrayList cases = RULE.getCases(board, testing_row); + + // assert correct number of cases created + Assert.assertEquals(1, cases.size()); + // Only one arrangement is possible when taking into account the + // touching tents contradiction rule. + + TreeTentBoard testCase = (TreeTentBoard) cases.getFirst(); + + // The two side tiles are tents, + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(0, 1).getType()); + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(2, 1).getType()); + + // and the center tile is grass. + Assert.assertEquals(TreeTentType.GRASS, testCase.getCell(1, 1).getType()); + + // 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 (h == 1) { + continue; + } + + original_cell = board.getCell(w, h); + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + + /* Test the Column */ + TreeTentClue testing_col = board.getClue(1, 3); + cases = RULE.getCases(board, testing_col); + + // assert correct number of cases created + Assert.assertEquals(1, cases.size()); + // Only one arrangement is possible when taking into account the + // touching tents contradiction rule. + + testCase = (TreeTentBoard) cases.getFirst(); + + // The two side tiles are tents, + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(1, 0).getType()); + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(1, 2).getType()); + + // and the center tile is grass. + Assert.assertEquals(TreeTentType.GRASS, testCase.getCell(1, 1).getType()); + + // checks other cells have not been modified + for (int w = 0; w < board.getWidth(); w++) { + for (int h = 0; h < board.getHeight(); h++) { + if (w == 1) { + continue; + } + + original_cell = board.getCell(w, h); + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests FillinRowCaseRule on row with 3 UNKNOWN tiles + * and a clue of 3 tent in the row. + * + *

checks that 0 cases are created + * + * @throws InvalidFileFormatException + */ + @Test + public void FillInRowEmptyThreeTentClue() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ThreeTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + /* Test the Row */ + TreeTentClue testing_row = board.getClue(3, 1); + ArrayList cases = RULE.getCases(board, testing_row); + + // assert there were no cases found, as filling in all tiles causes the tents to touch + Assert.assertNull(cases); + + /* Test the Column */ + TreeTentClue testing_col = board.getClue(1, 3); + cases = RULE.getCases(board, testing_row); + + Assert.assertNull(cases); + } + + /** + * empty 5x5 TreeTent puzzle Tests FillinRowCaseRule on row with 5 UNKNOWN tiles + * and a clue of 2 tents in the row. + * + *

checks that 6 cases are created and each case has the right number of tents + * + * @throws InvalidFileFormatException + */ + @Test + public void FillInRowEmpty5x5TwoTentClue() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/FillinRowCaseRule/EmptyRow5x5TwoTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + + // Test the Row + TreeTentClue testing_row = board.getClue(5, 2); + ArrayList cases = RULE.getCases(board, testing_row); + + // assert correct number of cases created + Assert.assertEquals(6, cases.size()); + // Only one arrangement is possible when taking into account the + // touching tents contradiction rule. + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + // Each case must have 2 tens in the row + Assert.assertEquals(2, testCase.getRowCol(2, TreeTentType.TENT, true).size()); + + // and they must have 3 grass tiles in the row + Assert.assertEquals(3, testCase.getRowCol(2, TreeTentType.GRASS, true).size()); + } + + TreeTentCell original_cell; + TreeTentCell case_cell; + + // checks other cells have not been modified + for (int w = 0; w < board.getWidth(); w++) { + for (int h = 0; h < board.getHeight(); h++) { + if (h == 2) { + continue; + } + + original_cell = board.getCell(w, h); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + + // Test the Column + TreeTentClue testing_col = board.getClue(2, 5); + cases = RULE.getCases(board, testing_col); + + // assert correct number of cases created + Assert.assertEquals(6, cases.size()); + // Only one arrangement is possible when taking into account the + // touching tents contradiction rule. + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + // Each case must have 2 tents in the column + Assert.assertEquals(2, testCase.getRowCol(2, TreeTentType.TENT, false).size()); + + // and they must have 4 grass tiles in the column + Assert.assertEquals(3, testCase.getRowCol(2, TreeTentType.GRASS, false).size()); + } + + // checks other cells have not been modified + for (int w = 0; w < board.getWidth(); w++) { + for (int h = 0; h < board.getHeight(); h++) { + if (w == 2) { + continue; + } + + original_cell = board.getCell(w, h); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard; + + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + } + + /** + * 7x3 TreeTent puzzle Tests FillinRowCaseRule on col with 3 UNKNOWN tiles separated by grass + * tiles and a clue of 3 tents in the col. + * + *

checks that 1 case is created and that all three UNKNOWN tiles have become tents + * + * @throws InvalidFileFormatException + */ + @Test + public void FillInRowPartialFillThreeTent() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/FillinRowCaseRule/PartialFillOneTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentClue testing_col = board.getClue(1, 7); + ArrayList cases = RULE.getCases(board, testing_col); + + // assert that one case was found + Assert.assertEquals(1, cases.size()); + + // assert the case has three tents in the column + TreeTentBoard testCase = (TreeTentBoard) cases.getFirst(); + Assert.assertEquals(3, testCase.getRowCol(1, TreeTentType.TENT, false).size()); + + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(1, 1).getType()); + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(1, 3).getType()); + Assert.assertEquals(TreeTentType.TENT, testCase.getCell(1, 5).getType()); + + // checks other cells have not been modified + TreeTentCell original_cell; + TreeTentCell case_cell; + + for (int w = 0; w < board.getWidth(); w++) { + if (w == 1) { + continue; + } + for (int h = 0; h < board.getHeight(); h++) { + + original_cell = board.getCell(w, h); + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } +} diff --git a/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java index 0783ab8b8..f37761e26 100644 --- a/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/FinishWithGrassDirectRuleTest.java @@ -28,14 +28,18 @@ 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 FinishWithGrassHorizontalTest() throws InvalidFileFormatException { + /** + * 3x3 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Tent at (1, 1) + * XXX x + * GTG 1 + * XXX x + * xxx + *

Makes (0, 1) and (2, 1) GRASS + * Checks if the rule detects the middle row to be filled in correctly + */ + @Test + public void FinishWithGrassHorizontalTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -74,14 +78,18 @@ public void FinishWithGrassHorizontalTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Tent at (0, 0) + * TXX x + * GXX x + * GXX x + * 1xx + *

Makes (0, 1) and (0, 2) GRASS + * Checks if the rule detects the leftmost column to be filled in correctly + */ + @Test + public void FinishWithGrassVerticalTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithGrassDirectRule/CornerTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -121,10 +129,14 @@ public void FinishWithGrassVerticalTest() throws InvalidFileFormatException { } /** - * 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 + * 3x3 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Tent at (0, 0) + * TGG 1 + * GXX x + * GXX x + * 1xx + *

Makes (0, 1), (0, 2), (1, 0), and (2, 0) GRASS + * Checks if the rule detects the top row and leftmost column to be filled in correctly */ @Test public void FinishWithGrassTest() throws InvalidFileFormatException { @@ -174,14 +186,18 @@ public void FinishWithGrassTest() throws InvalidFileFormatException { } } - /** - * 3x3 TreeTent puzzle with no tents Tests FinishWithGrassDirectRule on GRASS tiles GRASS tiles - * fill entire board - * - * @throws InvalidFileFormatException - */ - @Test - public void NoTentTest() throws InvalidFileFormatException { + /** + * 3x3 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Empty + * GGG 0 + * GGG 0 + * GGG 0 + * 000 + *

Fill Board with GRASS + * Checks if the rule allows all cells to be filled when the clue for all rows and columns is zero. + */ + @Test + public void NoTentTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithGrassDirectRule/NoTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -215,14 +231,18 @@ public void NoTentTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Tent at (1, 1) + * XGX x + * GTG 1 + * XGX x + * x1x + *

Makes (1, 0), (0, 1), (2, 1), and (1, 2) GRASS + * Checks if the rule correctly allows the central row and column to be filled with grass. + */ + @Test + public void MiddleTentTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithGrassDirectRule/MiddleTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -270,14 +290,18 @@ public void MiddleTentTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Empty + * GGG 1 + * GGG 1 + * GGG 1 + * 111 + *

Fill Board with GRASS + * Checks if the rule is not valid when a row or column does not have the required number of tents but is filled with grass + */ + @Test + public void FailTentTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithGrassDirectRule/FailTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -311,14 +335,22 @@ public void FailTentTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 7x7 TreeTent puzzle Tests FinishWithGrassDirectRule + *

Tents at (1, 3), (3, 3), and (5, 3) + * XXXXXXX x + * XXXXXXX x + * XXXXXXX x + * TGTGTGT 4 + * XXXXXXX x + * XXXXXXX x + * XXXXXXX x + * xxxxxxx + *

Makes (0, 3), (2, 3), (4, 3), and (6, 3) GRASS + * Checks if applying the rule on row 3 is valid + */ + @Test + public void SpacedOutTentTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithGrassDirectRule/SpacedOutTent", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); diff --git a/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java index 652af615f..d82be3f87 100644 --- a/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/FinishWithTentsDirectRuleTest.java @@ -27,14 +27,18 @@ public static void setUp() { 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Grass at (0, 0) + * GTT 2 + * XXX x + * XXX x + * xxx + *

Makes (1, 0) and (2, 0) TENT + * Checks that the rule correctly fills in the first row + */ + @Test + public void FinishWithHorizontalTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithHorizontalTents", treetent); @@ -67,14 +71,18 @@ public void FinishWithHorizontalTentsTest() throws InvalidFileFormatException { } } - /** - * 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 FinishWithVerticalTentsTest() throws InvalidFileFormatException { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Grass at (0, 0) + * GXX x + * TXX x + * TXX x + * 2xx + *

Makes (0, 1) and (0, 2) TENT + * Checks that the rule correctly fills in the first column + */ + @Test + public void FinishWithVerticalTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithVerticalTents", treetent); @@ -107,14 +115,18 @@ public void FinishWithVerticalTentsTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Grass at (0, 0) + * GTT 2 + * TXX x + * TXX x + * 2xx + *

Makes (1, 0), (2, 0), (0, 1) and (0, 2) TENT + * Checks that the rule correctly fills both the first row and first column + */ + @Test + public void FinishWithTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTents", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -155,14 +167,18 @@ public void FinishWithTentsTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Tent at (1, 1) + * XTX x + * TTT 3 + * XTX x + * x3x + *

Makes (1, 0), (0, 1), (2, 1), and (1, 2) TENT + * Checks that the rule correctly fills in the middle row and column when a tent starts at (1, 1) + */ + @Test + public void AdditionalTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/AdditionalTents", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -203,14 +219,18 @@ public void AdditionalTentsTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Empty + * TTT 0 + * TTT 0 + * TTT 0 + * 000 + *

Fills the board with tents + * Checks that the rule does not allow for more tents in any of the rows or columns + */ + @Test + public void FinishWithTentsFailTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/FinishWithTentsFail", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -239,15 +259,18 @@ public void FinishWithTentsFailTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Tent at (1, 1) + * XTX x + * TTT 1 + * XTX x + * x1x + *

Makes (1, 0), (0, 1), (2, 1) and (1, 2) Tent + * Checks that the rule does not allow for more tents in the central row or central column + */ + @Test + public void TooManyTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/TooManyTents", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -279,16 +302,18 @@ public void TooManyTentsTest() throws InvalidFileFormatException { } } - /** - * 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 { + /** + * 3x3 TreeTent puzzle Tests FinishWithTentsDirectRule + *

Tent at (1, 1) + * XTX x + * TTT 2 + * XTX x + * x2x + *

Makes (1, 0), (0, 1), (2, 1) and (1, 2) Tent + * Checks that the rule is not satisfied because there are multiple configurations of tents for the central row and central column + */ + @Test + public void AmbiguousTentsTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/FinishWithTentsDirectRule/AmbiguousTents", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); diff --git a/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java index 92d6e4a59..ad4559922 100644 --- a/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/LastCampingSpotDirectRuleTest.java @@ -26,13 +26,17 @@ 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_Up() throws InvalidFileFormatException { + /** + * 3x3 TreeTent puzzle Tests LastCampingSpotDirectRule + *

TREE at (1, 1) and (0, 1); GRASS at (1, 2) and (2, 1) + * XTX + * RRG + * XGX + *

Makes (1, 0) TENT + * Checks that a tent must be placed above the central tree + */ + @Test + public void EmptyFieldTest_Up() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotUp", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -60,13 +64,17 @@ public void EmptyFieldTest_Up() 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 { + /** + * 3x3 TreeTent puzzle Tests LastCampingSpotDirectRule + *

TREE at (1, 1) and (0, 1); GRASS at (1, 0) and (1, 2) + * XGX + * RRG + * XTX + *

Makes (1, 2) TENT + * Checks that a tent must be placed below the central tree + */ + @Test + public void EmptyFieldTest_Down() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotDown", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -94,13 +102,17 @@ public void EmptyFieldTest_Down() throws InvalidFileFormatException { } } - /** - * @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 { + /** + * 3x3 TreeTent puzzle Tests LastCampingSpotDirectRule + *

TREE at (1, 1) and (2, 1); GRASS at (1, 0) and (1, 2) + * XGX + * TRR + * XGX + *

Makes (0, 1) TENT + * Checks that a tent must be placed on the left of the central tree + */ + @Test + public void EmptyFieldTest_Left() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotLeft", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); @@ -128,13 +140,17 @@ public void EmptyFieldTest_Left() throws InvalidFileFormatException { } } - /** - * @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 { + /** + * 3x3 TreeTent puzzle Tests LastCampingSpotDirectRule + *

TREE at (1, 1) and (1, 2); GRASS at (0, 1) and (1, 0) + * XGX + * GRT + * XRX + *

Makes (2, 1) TENT + * Checks that a tent must be placed to the right of the central tree + */ + @Test + public void EmptyFieldTest_Right() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/LastCampingSpotDirectRule/LastCampingSpotRight", treetent); TreeNode rootNode = treetent.getTree().getRootNode(); diff --git a/src/test/java/puzzles/treetent/rules/LinkTentCaseRuleTest.java b/src/test/java/puzzles/treetent/rules/LinkTentCaseRuleTest.java new file mode 100644 index 000000000..3ed1fd79e --- /dev/null +++ b/src/test/java/puzzles/treetent/rules/LinkTentCaseRuleTest.java @@ -0,0 +1,191 @@ +package puzzles.treetent.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.tree.Tree; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.treetent.*; +import edu.rpi.legup.puzzle.treetent.rules.LinkTentCaseRule; +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.lang.reflect.Array; +import java.util.ArrayList; +import java.util.LinkedList; + +public class LinkTentCaseRuleTest { + private static final LinkTentCaseRule RULE = new LinkTentCaseRule(); + private static TreeTent treetent; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + treetent = new TreeTent(); + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tent + * with one tree surrounding it. + * + *

checks that 1 cases is with the line connecting the central tent and the tree + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentOneTreeTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTentCaseRule/OneTreeOneTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that one cases was found + Assert.assertEquals(1, cases.size()); + TreeTentBoard testCase = (TreeTentBoard) cases.getFirst(); + + TreeTentLine expectedLine = new TreeTentLine(board.getCell(1, 1), board.getCell(1, 0)); + + ArrayList lines = testCase.getLines(); + + // One line connecting the tree to the tent + Assert.assertEquals(1, lines.size()); + TreeTentLine line = lines.getFirst(); + + // Expected line + Assert.assertTrue(line.compare(expectedLine)); + + // 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++) { + original_cell = board.getCell(w, h); + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tent + * with four trees surrounding it. + * + *

checks that 4 cases are created, each of which create a line + * connecting the tent to one of the four trees without repeat. + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentFourTreesTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTentCaseRule/FourTreesOneTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that four cases were found + Assert.assertEquals(4, cases.size()); + + ArrayList expectedLines = new ArrayList<>(); + expectedLines.addFirst(new TreeTentLine(board.getCell(1, 1), board.getCell(1, 0))); + expectedLines.addFirst(new TreeTentLine(board.getCell(1, 1), board.getCell(0, 1))); + expectedLines.addFirst(new TreeTentLine(board.getCell(1, 1), board.getCell(2, 1))); + expectedLines.addFirst(new TreeTentLine(board.getCell(1, 1), board.getCell(1, 2))); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard ; + ArrayList lines = testCase.getLines(); + + // Each case should connect one line from the tent to + // one of the four trees next to it + Assert.assertEquals(1, lines.size()); + TreeTentLine line = lines.getFirst(); + + // Check to make sure that cases do not repeat + // and cover all four possibilities + boolean exists = false; + for (TreeTentLine expectedLine : expectedLines) { + if (line.compare(expectedLine)) { + expectedLines.remove(expectedLine); + exists = true; + break; + } + } + + Assert.assertTrue(exists); + + // 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++) { + original_cell = board.getCell(w, h); + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tent + * with zero trees around it. + * + *

Ensures no cases are created + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentNoTreesTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTentCaseRule/NoTrees", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that no cases were found + Assert.assertEquals(0, cases.size()); + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tent + * with trees on a diagonal. + * + *

Ensures no cases are created + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentDiagTreesTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTentCaseRule/DiagTrees", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that no cases were found + Assert.assertEquals(0, cases.size()); + } +} diff --git a/src/test/java/puzzles/treetent/rules/LinkTreeCaseRuleTest.java b/src/test/java/puzzles/treetent/rules/LinkTreeCaseRuleTest.java new file mode 100644 index 000000000..fffde14b1 --- /dev/null +++ b/src/test/java/puzzles/treetent/rules/LinkTreeCaseRuleTest.java @@ -0,0 +1,192 @@ +package puzzles.treetent.rules; + +import com.sun.source.doctree.LinkTree; +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.TreeTentLine; +import edu.rpi.legup.puzzle.treetent.rules.LinkTreeCaseRule; +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 LinkTreeCaseRuleTest { + private static final LinkTreeCaseRule RULE = new LinkTreeCaseRule(); + private static TreeTent treetent; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + treetent = new TreeTent(); + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tree + * with one tent above + * + *

Ensures one case is created that connects the tree to the tent. + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentOneTentTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTreeCaseRule/OneTent", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that no cases were found + Assert.assertEquals(1, cases.size()); + TreeTentBoard testCase = (TreeTentBoard) cases.getFirst(); + + TreeTentLine expectedLine = new TreeTentLine(board.getCell(1, 1), board.getCell(1, 0)); + + ArrayList lines = testCase.getLines(); + + // One line connecting the tree to the tent + Assert.assertEquals(1, lines.size()); + TreeTentLine line = lines.getFirst(); + + // Expected line + Assert.assertTrue(line.compare(expectedLine)); + + // 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++) { + original_cell = board.getCell(w, h); + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tree + * with two tents, one on the left and one on the right. + * + *

Ensures two cases are created, one connecting the tree and the + * left tent, and one connecting the tree and the right tent. + * Because tents must be surrounded by grass, there can be at most + * two tents around a given tree. + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentTwoTentsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTreeCaseRule/TwoTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that no cases were found + Assert.assertEquals(2, cases.size()); + + ArrayList expectedLines = new ArrayList<>(); + expectedLines.addFirst(new TreeTentLine(board.getCell(1, 1), board.getCell(0, 1))); + expectedLines.addFirst(new TreeTentLine(board.getCell(1, 1), board.getCell(2, 1))); + + for (Board testCaseBoard : cases) { + TreeTentBoard testCase = (TreeTentBoard) testCaseBoard ; + ArrayList lines = testCase.getLines(); + + // Each case should connect one line from the tent to + // either the left or right tree + Assert.assertEquals(1, lines.size()); + TreeTentLine line = lines.getFirst(); + + // Check to make sure that cases do not repeat + // and cover both possibilities + boolean exists = false; + for (TreeTentLine expectedLine : expectedLines) { + if (line.compare(expectedLine)) { + expectedLines.remove(expectedLine); + exists = true; + break; + } + } + + Assert.assertTrue(exists); + + // 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++) { + original_cell = board.getCell(w, h); + case_cell = testCase.getCell(w, h); + Assert.assertEquals(original_cell.getType(), case_cell.getType()); + } + } + } + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tree + * with zero tents around it. + * + *

Ensures no cases are created + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentNoTreesTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTreeCaseRule/NoTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that no cases were found + Assert.assertEquals(0, cases.size()); + } + + /** + * empty 3x3 TreeTent puzzle Tests LinkTentCaseRule on a central tree + * with tents on a diagonal. + * + *

Ensures no cases are created + * + * @throws InvalidFileFormatException + */ + @Test + public void LinkTentDiagTentsTest() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/LinkTreeCaseRule/NoTents", treetent); + TreeNode rootNode = treetent.getTree().getRootNode(); + TreeTransition transition = rootNode.getChildren().get(0); + transition.setRule(RULE); + + TreeTentBoard board = (TreeTentBoard) transition.getBoard(); + TreeTentCell test_location = board.getCell(1, 1); + ArrayList cases = RULE.getCases(board, test_location); + + // assert that no cases were found + Assert.assertEquals(0, cases.size()); + } +} diff --git a/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java index 7ff57a052..6177bb64c 100644 --- a/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/SurroundTentWithGrassDirectRuleTest.java @@ -27,12 +27,17 @@ 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 { + /** + * 3x3 TreeTent puzzle Tests SurroundTentWithGrassDirectRule + *

TREE at (0, 0), (2, 0), (0, 1), (2, 1), (1, 2), and (2, 2); TENT at (1, 1) + * RGR + * RTR + * GRR + *

Makes (1, 0) and (0, 2) GRASS + * Checks that the rule detects unknown adjacent and diagonal tiles correctly + */ + @Test + public void SurroundTentWithGrassBasicRuleTest() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrass", treetent); @@ -64,14 +69,17 @@ 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 { + /** + * 3x3 TreeTent puzzle Tests SurroundTentWithGrassDirectRule + *

TENT at (1, 1) + * GGG + * GTG + * GGG + *

Makes all cells adjacent and diagonal to the tent GRASS + * Checks that the rule detects all adjacent and diagonal tiles correctly + */ + @Test + public void SurroundTentWithGrassBasicRuleTest_BadBoard() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassBad", treetent); @@ -129,13 +137,17 @@ public void SurroundTentWithGrassBasicRuleTest_BadBoard() throws InvalidFileForm } } - /** - * @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 { + /** + * 3x3 TreeTent puzzle Tests SurroundTentWithGrassDirectRule + *

TENT at (1, 1); TREE on all adjacent and diagonal tiles + * RRR + * RTR + * RRR + *

Null + * Checks that the rule correctly detects no missing tiles + */ + @Test + public void SurroundTentWithGrassBasicRuleTest_FullBoard() throws InvalidFileFormatException { TestUtilities.importTestBoard( "puzzles/treetent/rules/SurroundTentWithGrassDirectRule/SurroundTentWithGrassTrees", treetent); diff --git a/src/test/java/puzzles/treetent/rules/TentForTreeDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/TentForTreeDirectRuleTest.java index 68dbeaf48..e55704ec2 100644 --- a/src/test/java/puzzles/treetent/rules/TentForTreeDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TentForTreeDirectRuleTest.java @@ -1,14 +1,167 @@ package puzzles.treetent.rules; -// This feature is no longer supported +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.treetent.*; +import edu.rpi.legup.puzzle.treetent.rules.TentForTreeDirectRule; +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 TentForTreeDirectRuleTest { - // private static final TentForTreeBasicRule RULE = new TentForTreeBasicRule(); - // private static TreeTent treetent; - // - // @BeforeClass - // public static void setUp() { - // MockGameBoardFacade.getInstance(); - // treetent = new TreeTent(); - // } + private static final TentForTreeDirectRule RULE = new TentForTreeDirectRule(); + private static TreeTent treetent; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + treetent = new TreeTent(); + } + + /** + * 3x3 TreeTent puzzle Tests TentForTreeDirectRule + *

TREE at (1, 0); TENT at (1, 1) + * XRX + * XTX + * XXX + *

Makes a line between (1, 0) and (1, 1) + * Checks that the rule correctly detects the central tent as the only possible connection + */ + @Test + public void TentForTreeTestOneTreeOneTentTest() throws InvalidFileFormatException { + + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TentForTreeDirectRule/OneTreeOneTent", + 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, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNull(RULE.checkRule(transition)); + + ArrayList lines = board.getLines(); + for (TreeTentLine l : lines) { + if (l.compare((line))) { + Assert.assertNull(RULE.checkRuleAt(transition, l)); + } else { + Assert.assertNotNull(RULE.checkRuleAt(transition, l)); + } + } + } + + /** + * 3x3 TreeTent puzzle Tests TentForTreeDirectRule + *

TREE at (1, 0) and (1, 2); TENT at (1, 1) + * XRX + * XTX + * XRX + *

Makes a line between (1, 0) and (1, 1) + * Checks that the rule works when connecting a line between the tree at (1, 0) and tent at (1, 1) + */ + @Test + public void TentForTreeArbitraryTreeTest() throws InvalidFileFormatException { + + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TentForTreeDirectRule/ArbitraryTree", + 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, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * 3x3 TreeTent puzzle Tests TentForTreeDirectRule + *

TREE at (1, 0) and (1, 2); TENT at (1, 1); LINE between (1, 0) and (1, 1) + * XRX + * XTX + * XRX + *

Makes a line between (1, 1) and (1, 2) + * Checks that the rule fails for the tree at (1, 2) because there are no valid tents to connect to + */ + @Test + public void TentForTreeConnectedTent() throws InvalidFileFormatException { + + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TentForTreeDirectRule/ArbitraryTree", + 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); + TreeTentCell cell2 = board.getCell(1, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNull(RULE.checkRule(transition)); + + ArrayList lines = board.getLines(); + for (TreeTentLine l : lines) { + Assert.assertNotNull(RULE.checkRuleAt(transition, l)); + } + } + + /** + * 3x3 TreeTent puzzle Tests TentForTreeDirectRule + *

TREE at (1, 1); TENT at (1, 0) and (1, 2) + * XTX + * XRX + * XTX + *

Makes a line between (1, 1) and (1, 2) + * Checks that the rule fails for the tree at (1, 1) because there are two valid tents to connect to + */ + @Test + public void TentForTreeOneTreeTwoAdjacentTent() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TentForTreeDirectRule/OneTreeTwoAdjacentTent", + 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); + TreeTentCell cell2 = board.getCell(1, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNotNull(RULE.checkRule(transition)); + } } diff --git a/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java index 2e542b3d2..c1dc6380a 100644 --- a/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TooManyTentsContradictionRuleTest.java @@ -29,7 +29,7 @@ public static void setUp() { 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) + There are tents at (1,0) and (2,2) All Tent Counts are listed left to right or top to bottom */ diff --git a/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java b/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java index 9f5455a92..e44543ab6 100644 --- a/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TouchingTentsContradictionRuleTest.java @@ -135,90 +135,6 @@ public void TouchingTentsContradictionRule_2By2Square() throws InvalidFileFormat 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 */ @@ -254,6 +170,6 @@ public void TouchingTentsContradictionRule_TreeDiagonal() throws InvalidFileForm 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(1, 1))); } } diff --git a/src/test/java/puzzles/treetent/rules/TreeForTentDirectRuleTest.java b/src/test/java/puzzles/treetent/rules/TreeForTentDirectRuleTest.java index f4ea6703b..ba1b49b8c 100644 --- a/src/test/java/puzzles/treetent/rules/TreeForTentDirectRuleTest.java +++ b/src/test/java/puzzles/treetent/rules/TreeForTentDirectRuleTest.java @@ -1,14 +1,161 @@ package puzzles.treetent.rules; -// This feature is no longer supported +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.TreeTentLine; +import edu.rpi.legup.puzzle.treetent.rules.TreeForTentDirectRule; +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 TreeForTentDirectRuleTest { - // private static final TreeForTentBasicRule RULE = new TreeForTentBasicRule(); - // private static TreeTent treetent; + private static final TreeForTentDirectRule RULE = new TreeForTentDirectRule(); + private static TreeTent treetent; + + @BeforeClass + public static void setUp() { + MockGameBoardFacade.getInstance(); + treetent = new TreeTent(); + } + + /** + * 3x3 TreeTent puzzle Tests TreeForTentDirectRule + *

TENT at (1, 0); TREE at (1, 1) + * XTX + * XRX + * XXX + *

Makes a line between (1, 0) and (1, 1) + * Checks that the rule correctly detects the central tree as the only possible connection + */ + @Test + public void TreeForTentTestOneTreeOneTentTest() throws InvalidFileFormatException { + + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TreeForTentDirectRule/OneTentOneTree", + 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, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * 3x3 TreeTent puzzle Tests TreeForTentDirectRule + *

TENT at (1, 0) and (1, 2); TREE at (1, 1) + * XTX + * XRX + * XTX + *

Makes a line between (1, 0) and (1, 1) + * Checks that the rule works when connecting a line between the tent at (1, 0) and the tree at (1, 1) + */ + @Test + public void TentForTreeWithArbitraryTreeTest() throws InvalidFileFormatException { + + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TreeForTentDirectRule/ArbitraryTent", + 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, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNull(RULE.checkRule(transition)); + } + + /** + * 3x3 TreeTent puzzle Tests TreeForTentDirectRule + *

TENT at (1, 0) and (1, 2); TREE at (1, 1); LINE between (1, 0) and (1, 1) + * XTX + * XRX + * XTX + *

Makes a line between (1, 1) and (1, 2) + * Checks that the rule fails for the tent at (1, 2) because there are no valid trees to connect to + */ + @Test + public void TentForTreeConnectedTent() throws InvalidFileFormatException { + + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TreeForTentDirectRule/ConnectedTree", + 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); + TreeTentCell cell2 = board.getCell(1, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); + + Assert.assertNull(RULE.checkRule(transition)); + + ArrayList lines = board.getLines(); + for (TreeTentLine l : lines) { + Assert.assertNotNull(RULE.checkRuleAt(transition, l)); + } + } + + /** + * 3x3 TreeTent puzzle Tests TreeForTentDirectRule + *

TENT at (1, 1); TREE at (1, 0) and (1, 2) + * XRX + * XTX + * XRX + *

Makes a line between (1, 1) and (1, 2) + * Checks that the rule fails for the tree at (1, 1) because there are two valid trees to connect to + */ + @Test + public void TentForTreeOneTreeTwoAdjacentTent() throws InvalidFileFormatException { + TestUtilities.importTestBoard( + "puzzles/treetent/rules/TreeForTentDirectRule/OneTentTwoAdjacentTrees", + 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); + TreeTentCell cell2 = board.getCell(1, 1); + TreeTentLine line = new TreeTentLine(cell1, cell2); + + board.addModifiedData(line); + board.getLines().add(line); - // @BeforeClass - // public static void setUp() { - // MockGameBoardFacade.getInstance(); - // treetent = new TreeTent(); - // } + Assert.assertNotNull(RULE.checkRule(transition)); + } } diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3OneTent similarity index 78% rename from src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft rename to src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3OneTent index d19e01daf..1e1259a44 100644 --- a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailLeft +++ b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3OneTent @@ -2,16 +2,15 @@ - - + - + diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ThreeTent similarity index 78% rename from src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight rename to src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ThreeTent index bf3954964..7c352347d 100644 --- a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailRight +++ b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ThreeTent @@ -2,16 +2,15 @@ - - + - + diff --git a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3TwoTent similarity index 57% rename from src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft rename to src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3TwoTent index af4ca0831..1f4a907eb 100644 --- a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownLeft +++ b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3TwoTent @@ -1,18 +1,17 @@ - + - - - - + + - + + diff --git a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ZeroTent similarity index 92% rename from src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom rename to src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ZeroTent index 80deadaea..a13c7cc55 100644 --- a/src/test/resources/puzzles/treetent/rules/EmptyFieldDirectRule/EmptyFieldFailBottom +++ b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow3x3ZeroTent @@ -2,7 +2,6 @@ - diff --git a/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow5x5TwoTent b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow5x5TwoTent new file mode 100644 index 000000000..ddfcf44db --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/EmptyRow5x5TwoTent @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/PartialFillOneTent b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/PartialFillOneTent new file mode 100644 index 000000000..47d06d5b9 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/FillinRowCaseRule/PartialFillOneTent @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/DiagTrees b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/DiagTrees new file mode 100644 index 000000000..4a10b61f2 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/DiagTrees @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/FourTreesOneTent b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/FourTreesOneTent new file mode 100644 index 000000000..96a06de3b --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/FourTreesOneTent @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/NoTrees b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/NoTrees new file mode 100644 index 000000000..c781cfde9 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/NoTrees @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/OneTreeOneTent b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/OneTreeOneTent new file mode 100644 index 000000000..103c1ce3e --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTentCaseRule/OneTreeOneTent @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/DiagTents b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/DiagTents new file mode 100644 index 000000000..e50bef8c1 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/DiagTents @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/NoTents b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/NoTents new file mode 100644 index 000000000..3bab63f75 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/NoTents @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/OneTent b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/OneTent new file mode 100644 index 000000000..69eb680de --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/OneTent @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/TwoTents b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/TwoTents new file mode 100644 index 000000000..7fb4b6e46 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/LinkTreeCaseRule/TwoTents @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ArbitraryTree b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ArbitraryTree new file mode 100644 index 000000000..258ebec21 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ArbitraryTree @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ConnectedTent b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ConnectedTent new file mode 100644 index 000000000..031bca068 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/ConnectedTent @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeOneTent b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeOneTent new file mode 100644 index 000000000..dcc428c8b --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeOneTent @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeTwoAdjacentTent b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeTwoAdjacentTent new file mode 100644 index 000000000..508cda0a8 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TentForTreeDirectRule/OneTreeTwoAdjacentTent @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 deleted file mode 100644 index 05b7a7667..000000000 --- a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedDownRight +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ 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 deleted file mode 100644 index b8b81c7b4..000000000 --- a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpLeft +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ 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 deleted file mode 100644 index af7fb5df2..000000000 --- a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsMixedUpRight +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ 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 index b2f54aef3..b25eb6c4c 100644 --- a/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeDiagonal +++ b/src/test/resources/puzzles/treetent/rules/TouchingTentsContradictionRule/TouchingTentsTreeDiagonal @@ -3,7 +3,7 @@ - + diff --git a/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ArbitraryTent b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ArbitraryTent new file mode 100644 index 000000000..ce083cfc0 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ArbitraryTent @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ConnectedTree b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ConnectedTree new file mode 100644 index 000000000..6ebecc06f --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/ConnectedTree @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentOneTree b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentOneTree new file mode 100644 index 000000000..fabfe06e2 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentOneTree @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentTwoAdjacentTrees b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentTwoAdjacentTrees new file mode 100644 index 000000000..8218fb2f1 --- /dev/null +++ b/src/test/resources/puzzles/treetent/rules/TreeForTentDirectRule/OneTentTwoAdjacentTrees @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 0e8ae65e05c3385e5e1e3a506645f75b2a80dffc Mon Sep 17 00:00:00 2001 From: Kevin Xu <35581753+kevinkxu@users.noreply.github.com> Date: Sun, 5 May 2024 13:42:20 -0400 Subject: [PATCH 2/3] Issue 784 (#790) * one region color ripple effect * wip * remove irrelevant file * wip * wip2 * save as for proof editor * proof editor fix --------- Co-authored-by: Charles Tian <46334090+charlestian23@users.noreply.github.com> --- .../edu/rpi/legup/ui/ProofEditorPanel.java | 34 ++++----- .../edu/rpi/legup/ui/PuzzleEditorPanel.java | 71 +++++++++++-------- 2 files changed, 57 insertions(+), 48 deletions(-) diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java index 956f83ba4..8401e19f2 100644 --- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -580,31 +580,31 @@ private void saveProofAs() { if (puzzle == null) { return; } - - fileDialog.setMode(FileDialog.SAVE); - fileDialog.setTitle("Save As"); - String curFileName = GameBoardFacade.getInstance().getCurFileName(); - if (curFileName == null) { - fileDialog.setDirectory( - LegupPreferences.getInstance().getUserPref(LegupPreferences.WORK_DIRECTORY)); - } else { - File curFile = new File(curFileName); - fileDialog.setDirectory(curFile.getParent()); + + LegupPreferences preferences = LegupPreferences.getInstance(); + File preferredDirectory = + new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY)); + if (preferences.getSavedPath() != "") { + preferredDirectory = new File(preferences.getSavedPath()); } - fileDialog.setVisible(true); + folderBrowser = new JFileChooser(preferredDirectory); - String fileName = null; - if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) { - fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile(); - } + folderBrowser.showSaveDialog(this); + folderBrowser.setVisible(true); + folderBrowser.setCurrentDirectory(new File(LegupPreferences.WORK_DIRECTORY)); + folderBrowser.setDialogTitle("Select Directory"); + folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + folderBrowser.setAcceptAllFileFilterUsed(false); - if (fileName != null) { + String path = folderBrowser.getSelectedFile().getAbsolutePath(); + + if (path != null) { try { PuzzleExporter exporter = puzzle.getExporter(); if (exporter == null) { throw new ExportFileException("Puzzle exporter null"); } - exporter.exportPuzzle(fileName); + exporter.exportPuzzle(path); } catch (ExportFileException e) { e.printStackTrace(); } diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java index b3cd30ffb..f50c8d6fc 100644 --- a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java @@ -35,6 +35,7 @@ public class PuzzleEditorPanel extends LegupPanel implements IHistoryListener { private JMenuItem helpLegup, aboutLegup; private JMenuBar menuBar; private JToolBar toolBar; + private JFileChooser folderBrowser; private JFrame frame; private JButton[] buttons; JSplitPane splitPanel; @@ -380,25 +381,37 @@ public void loadPuzzleFromHome(String game, String[] statements) { public Object[] promptPuzzle() { GameBoardFacade facade = GameBoardFacade.getInstance(); if (facade.getBoard() != null) { - if (noQuit("Opening a new puzzle to edit?")) { + if (noQuit("Opening a new puzzle?")) { return new Object[0]; } } - if (fileDialog == null) { - fileDialog = new FileDialog(this.frame); - } + LegupPreferences preferences = LegupPreferences.getInstance(); String preferredDirectory = preferences.getUserPref(LegupPreferences.WORK_DIRECTORY); + if (preferences.getSavedPath() != "") { + preferredDirectory = preferences.getSavedPath(); + } - fileDialog.setMode(FileDialog.LOAD); - fileDialog.setTitle("Select Puzzle"); - fileDialog.setDirectory(preferredDirectory); - fileDialog.setVisible(true); + File preferredDirectoryFile = new File(preferredDirectory); + JFileChooser fileBrowser = new JFileChooser(preferredDirectoryFile); String fileName = null; File puzzleFile = null; - if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) { - fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile(); - puzzleFile = new File(fileName); + + fileBrowser.showOpenDialog(this); + fileBrowser.setVisible(true); + fileBrowser.setCurrentDirectory(new File(preferredDirectory)); + fileBrowser.setDialogTitle("Select Proof File"); + fileBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileBrowser.setAcceptAllFileFilterUsed(false); + + File puzzlePath = fileBrowser.getSelectedFile(); + System.out.println(puzzlePath.getAbsolutePath()); + + if (puzzlePath != null) { + fileName = puzzlePath.getAbsolutePath(); + String lastDirectoryPath = fileName.substring(0, fileName.lastIndexOf(File.separator)); + preferences.setSavedPath(lastDirectoryPath); + puzzleFile = puzzlePath; } else { // The attempt to prompt a puzzle ended gracefully (cancel) return null; @@ -538,39 +551,35 @@ private String savePuzzle() { } } - if (fileDialog == null) { - fileDialog = new FileDialog(this.frame); + LegupPreferences preferences = LegupPreferences.getInstance(); + File preferredDirectory = + new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY)); + if (preferences.getSavedPath() != "") { + preferredDirectory = new File(preferences.getSavedPath()); } + folderBrowser = new JFileChooser(preferredDirectory); - fileDialog.setMode(FileDialog.SAVE); - fileDialog.setTitle("Save Proof"); - String curFileName = GameBoardFacade.getInstance().getCurFileName(); - if (curFileName == null) { - fileDialog.setDirectory( - LegupPreferences.getInstance().getUserPref(LegupPreferences.WORK_DIRECTORY)); - } else { - File curFile = new File(curFileName); - fileDialog.setDirectory(curFile.getParent()); - } - fileDialog.setVisible(true); + folderBrowser.showSaveDialog(this); + folderBrowser.setVisible(true); + folderBrowser.setCurrentDirectory(new File(LegupPreferences.WORK_DIRECTORY)); + folderBrowser.setDialogTitle("Select Directory"); + folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + folderBrowser.setAcceptAllFileFilterUsed(false); - String fileName = null; - if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) { - fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile(); - } + String path = folderBrowser.getSelectedFile().getAbsolutePath(); - if (fileName != null) { + if (path != null) { try { PuzzleExporter exporter = puzzle.getExporter(); if (exporter == null) { throw new ExportFileException("Puzzle exporter null"); } - exporter.exportPuzzle(fileName); + exporter.exportPuzzle(path); } catch (ExportFileException e) { e.printStackTrace(); } } - return fileName; + return path; } public DynamicView getDynamicBoardView() { From 58eba415dcde10b9b8f26ccfea2ee79af4ba58d3 Mon Sep 17 00:00:00 2001 From: Brandon McCusker Date: Sun, 5 May 2024 13:46:44 -0400 Subject: [PATCH 3/3] Binary (#812) * Test commit * Test commit again * Implementing the constructor and some abstract methods * Implementing the BinaryType file for the grid cell possibilities * initialized puzzle files, began writing the puzzle importer and finished most of binary.java functionality * Finished setting up BinaryImporter completely with all helper files (BinaryView, BinaryCellFactory, BinaryController, BinaryElementView). These files create the grid view of the puzzle and are responsible for the GUI of the puzzle. * Fixed bugs in binary files, wrote binary exporter * Fixed compile errors * Added binary puzzle to config, began writing rules * Fixed minor syntax and import error * Fixed checkstyle error message in BinaryCellFactory * Made slight progress when trying to output puzzle, first edition of Three Adjacent Ones and Zeros Contradiction rules * Fixed checkstyle error for if statements * Added functions to BinaryBoard that returns the rows and columns of a specified index. * Fixed error that causes BinaryImporter to fail to initialize board * First edition of Unbalanced Row and Unbalanced Column Contradiction rules * Update config * Deleted false config file, began rule implementation, began fixing puzzle board visual * Fixed stylecheck errors * First edition of Duplicate Rows and Duplicate Columns Contradiction rules * First edition of One Tile Gap Direct rule * Second edition of One Tile Gap Direct rule, typo in if statement * Initial Board Rendering correct * All user board interactions fiex to be correct * Altered given cells color and fixed rules ref * Added temporary images to rules * Fixed checkStyle error * Changed Direct Rule * Create MyWikiContributions * Rename MyWikiContributions to MyWikiContributions.md * Combined each of the contradiction rules into one file rather than two separate files * Fixed checkStyle error in ThreeAdjacentContradictionRule * Wrote prelim OneZeroCaseRule * Fixed bugs and continued Contradiciton rule work * Added copy in BinaryBoard, fixed getCell with checking out of bounds * Three adjacent CR complete and prelim testing done * Tested UnbalancedRowOrColumnContradictionRule to verify correction Fixed checkStyle errors * Tested UnbalancedRowOrColumnContradictionRule to verify correction Fixed checkStyle errors * Fixed checkStyle error in ThreeAdjacentContradictionRule * Deleted unnecessary file that was auto created * OneZeroCaseRule working version complete, began writing SurroundPairDIrectRule fixed minor bugs * Finished DuplicateRowsOrColumnsContradictionRule for rows but not columns, added method to get all types of cells in row. * fixed stylecheck errors * fixed stylecheck errors * All rules complete and ready for test suite, constructed additional test puzzles * Cleaned rule files, unified formatting, removed print statements from testing * Cleaned rule files, unified formatting, removed print statements from testing, fixed minor bug * Found error in ThreeAdjacentContradictionRule, missing valid contradictions in OneTileGap and SurroundPair Direct Rules * Fixed checkStyle error "if construct must use {}'s" * Fixed buggy three adjacent contradiction rule * Made slight progress in onetilegap direct rule * Slight progress with SurroundPairDirectRule * Completed and tested all rules to verify correctness. * Added final rule images, adjusted nming converntions for rule images, updated wiki with new rule images * Added Wiki Contributions * Added Binary Puzzle Presentation * Added Wiki Contributions * Add files via upload * Made improvement to rule images * Delete LEGUP Binary Puzzle Progress.pptx * Delete LEGUPBinaryPuzzleProgress.pptx * Delete WikiContributions.md * deleted blank file * Automated Java code formatting changes --------- Co-authored-by: zachbonagura Co-authored-by: zachbonagura <157537291+zachbonagura@users.noreply.github.com> Co-authored-by: charlestian23 Co-authored-by: Charles Tian <46334090+charlestian23@users.noreply.github.com> Co-authored-by: Bram van Heuveln --- bin/main/edu/rpi/legup/legup/config | 47 ------- puzzles files/binary/6x6 easy/089764562 | 22 +++ puzzles files/binary/6x6 easy/128903434 | 21 +++ puzzles files/binary/6x6 easy/876868768 | 25 ++++ puzzles files/binary/6x6 easy/927364891 | 28 ++++ .../rpi/legup/model/gameboard/GridRegion.java | 16 ++- .../edu/rpi/legup/puzzle/binary/Binary.java | 71 ++++++++++ .../rpi/legup/puzzle/binary/BinaryBoard.java | 84 ++++++++++++ .../rpi/legup/puzzle/binary/BinaryCell.java | 35 +++++ .../puzzle/binary/BinaryCellFactory.java | 59 ++++++++ .../legup/puzzle/binary/BinaryController.java | 45 +++++++ .../puzzle/binary/BinaryElementView.java | 120 +++++++++++++++++ .../legup/puzzle/binary/BinaryExporter.java | 39 ++++++ .../legup/puzzle/binary/BinaryImporter.java | 117 ++++++++++++++++ .../rpi/legup/puzzle/binary/BinaryType.java | 11 ++ .../rpi/legup/puzzle/binary/BinaryView.java | 24 ++++ .../puzzle/binary/elements/BlankTile.java | 1 + .../puzzle/binary/elements/NumberTile.java | 1 + .../rules/CompleteRowColumnDirectRule.java | 55 ++++++++ ...plicateRowsOrColumnsContradictionRule.java | 55 ++++++++ .../binary/rules/OneOrZeroCaseRule.java | 90 +++++++++++++ .../binary/rules/OneTileGapDirectRule.java | 64 +++++++++ .../binary/rules/SurroundPairDirectRule.java | 48 +++++++ .../rules/ThreeAdjacentContradictionRule.java | 127 ++++++++++++++++++ ...nbalancedRowOrColumnContradictionRule.java | 68 ++++++++++ .../binary/rules/binary_reference_sheet.txt | 9 ++ .../legup/puzzle/starbattle/StarBattle.java | 4 +- .../puzzle/starbattle/StarBattleBoard.java | 20 +-- .../puzzle/starbattle/StarBattleCell.java | 29 ++-- .../starbattle/StarBattleCellFactory.java | 26 ++-- .../puzzle/starbattle/StarBattleCellType.java | 10 +- .../starbattle/StarBattleController.java | 20 +-- .../starbattle/StarBattleElementView.java | 11 +- .../puzzle/starbattle/StarBattleExporter.java | 6 +- .../puzzle/starbattle/StarBattleImporter.java | 31 ++--- .../puzzle/starbattle/StarBattleRegion.java | 6 +- .../puzzle/starbattle/StarBattleView.java | 25 ++-- .../puzzle/starbattle/elements/BlackTile.java | 6 +- .../puzzle/starbattle/elements/StarTile.java | 6 +- .../starbattle/elements/UnknownTile.java | 6 +- .../puzzle/starbattle/elements/WhiteTile.java | 7 +- .../starbattle/rules/BlackoutDirectRule.java | 18 +-- .../rules/ClashingOrbitContradictionRule.java | 25 ++-- .../rules/ColumnsWithinRegionsDirectRule.java | 39 +++--- .../rules/ColumnsWithinRowsDirectRule.java | 38 +++--- .../rules/FinishWithStarsDirectRule.java | 16 ++- .../rules/RegionsWithinColumnsDirectRule.java | 16 ++- .../rules/RegionsWithinRowsDirectRule.java | 16 ++- .../rules/RowsWithinColumnsDirectRule.java | 22 ++- .../rules/RowsWithinRegionsDirectRule.java | 38 +++--- .../starbattle/rules/StarOrEmptyCaseRule.java | 33 ++--- .../rules/SurroundStarDirectRule.java | 17 +-- .../rules/TooFewStarsContradictionRule.java | 17 ++- .../rules/TooManyStarsContradictionRule.java | 19 ++- .../edu/rpi/legup/utility/LegupUtils.java | 3 +- .../rules/CompleteRowColumnDirectRule.png | Bin 0 -> 2835 bytes .../DuplicateRowOrColumnContradictionRule.png | Bin 0 -> 3455 bytes .../images/binary/rules/OneOrZeroCaseRule.png | Bin 0 -> 5578 bytes .../binary/rules/OneTileGapDirectRule.png | Bin 0 -> 2751 bytes .../binary/rules/SurroundPairDirectRule.png | Bin 0 -> 2982 bytes .../rules/ThreeAdjacentContradictionRule.png | Bin 0 -> 2508 bytes .../UnbalancedRowColumnContradictionRule.png | Bin 0 -> 2793 bytes src/main/resources/edu/rpi/legup/legup/config | 4 + 63 files changed, 1506 insertions(+), 310 deletions(-) delete mode 100644 bin/main/edu/rpi/legup/legup/config create mode 100644 puzzles files/binary/6x6 easy/089764562 create mode 100644 puzzles files/binary/6x6 easy/128903434 create mode 100644 puzzles files/binary/6x6 easy/876868768 create mode 100644 puzzles files/binary/6x6 easy/927364891 create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/Binary.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryBoard.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryCell.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryCellFactory.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryController.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryElementView.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryExporter.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryImporter.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryType.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/BinaryView.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/elements/BlankTile.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/elements/NumberTile.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/OneTileGapDirectRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/SurroundPairDirectRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/ThreeAdjacentContradictionRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/binary/rules/binary_reference_sheet.txt create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/OneOrZeroCaseRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/OneTileGapDirectRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png diff --git a/bin/main/edu/rpi/legup/legup/config b/bin/main/edu/rpi/legup/legup/config deleted file mode 100644 index 4aef6de60..000000000 --- a/bin/main/edu/rpi/legup/legup/config +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/puzzles files/binary/6x6 easy/089764562 b/puzzles files/binary/6x6 easy/089764562 new file mode 100644 index 000000000..7b22ffc10 --- /dev/null +++ b/puzzles files/binary/6x6 easy/089764562 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/puzzles files/binary/6x6 easy/128903434 b/puzzles files/binary/6x6 easy/128903434 new file mode 100644 index 000000000..ea8ef93b0 --- /dev/null +++ b/puzzles files/binary/6x6 easy/128903434 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/puzzles files/binary/6x6 easy/876868768 b/puzzles files/binary/6x6 easy/876868768 new file mode 100644 index 000000000..0f0ff745e --- /dev/null +++ b/puzzles files/binary/6x6 easy/876868768 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/puzzles files/binary/6x6 easy/927364891 b/puzzles files/binary/6x6 easy/927364891 new file mode 100644 index 000000000..da76d067b --- /dev/null +++ b/puzzles files/binary/6x6 easy/927364891 @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java index 6718ab6f4..c41d5e1b2 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java @@ -4,18 +4,17 @@ import java.util.List; public abstract class GridRegion { - + protected List regionCells; - - /** - * Region Constructor - */ + + /** Region Constructor */ public GridRegion() { this.regionCells = new ArrayList<>(); } /** * Adds the cell to the region + * * @param cell cell to be added to the region */ public void addCell(T cell) { @@ -24,6 +23,7 @@ public void addCell(T cell) { /** * Removes the cell from the region + * * @param cell cell to be remove from the region */ public void removeCell(T cell) { @@ -32,6 +32,7 @@ public void removeCell(T cell) { /** * Returns the list of cells in the region + * * @return list of cells in region */ public List getCells() { @@ -40,14 +41,15 @@ public List getCells() { /** * Returns the number of cells in the region + * * @return number of cells in the region */ - public int getSize(){ + public int getSize() { return regionCells.size(); } /* public void colorRegion(){} */ - + } diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/Binary.java b/src/main/java/edu/rpi/legup/puzzle/binary/Binary.java new file mode 100644 index 000000000..773513cda --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/Binary.java @@ -0,0 +1,71 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.model.Puzzle; +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; + +public class Binary extends Puzzle { + public Binary() { + super(); + + this.name = "Binary"; + + this.importer = new BinaryImporter(this); + this.exporter = new BinaryExporter(this); + + this.factory = new BinaryCellFactory(); + } + + /** Initializes the game board. Called by the invoker of the class */ + @Override + public void initializeView() { + boardView = new BinaryView((BinaryBoard) currentBoard); + boardView.setBoard(currentBoard); + addBoardListener(boardView); + } + + /** + * Generates a random edu.rpi.legup.puzzle based on the difficulty + * + * @param difficulty level of difficulty (1-10) + * @return board of the random edu.rpi.legup.puzzle + */ + @Override + public Board generatePuzzle(int difficulty) { + return null; + } + + // /** + // * Determines if the given dimensions are valid for Binary + // * + // * @param rows the number of rows + // * @param columns the number of columns + // * @return true if the given dimensions are valid for Binary, false otherwise + // */ + // @Override + // public boolean isValidDimensions(int rows, int columns){ + // return rows >= 2 && rows % 2 == 0 && columns >= 2 && columns % 2 == 0; + // } + + @Override + public boolean isBoardComplete(Board board) { + BinaryBoard binaryBoard = (BinaryBoard) board; + + for (ContradictionRule rule : contradictionRules) { + if (rule.checkContradiction(binaryBoard) == null) { + return false; + } + } + for (PuzzleElement data : binaryBoard.getPuzzleElements()) { + BinaryCell cell = (BinaryCell) data; + if (cell.getType() == BinaryType.UNKNOWN) { + return false; + } + } + return true; + } + + @Override + public void onBoardChange(Board board) {} +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryBoard.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryBoard.java new file mode 100644 index 000000000..35c37b1a1 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryBoard.java @@ -0,0 +1,84 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.model.gameboard.GridBoard; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +public class BinaryBoard extends GridBoard { + private int size; + + public BinaryBoard(int width, int height) { + super(width, height); + this.size = width; + } + + public BinaryBoard(int size) { + super(size, size); + this.size = size; + } + + @Override + public BinaryCell getCell(int x, int y) { + if (y * dimension.width + x >= puzzleElements.size() + || x >= dimension.width + || y >= dimension.height + || x < 0 + || y < 0) { + return null; + } + return (BinaryCell) super.getCell(x, y); + } + + public Set getRowCells(int rowNum) { + Set row = new HashSet<>(); + for (int i = 0; i < size; i++) { + BinaryCell cell = getCell(i, rowNum); + row.add(cell); + } + return row; + } + + public ArrayList getRowTypes(int rowNum) { + ArrayList row = new ArrayList(); + for (int i = 0; i < size; i++) { + BinaryCell cell = getCell(i, rowNum); + row.add(cell.getType()); + } + return row; + } + + public ArrayList getColTypes(int colNum) { + ArrayList col = new ArrayList(); + for (int i = 0; i < size; i++) { + BinaryCell cell = getCell(colNum, i); + col.add(cell.getType()); + } + return col; + } + + public Set getCol(int colNum) { + Set col = new HashSet<>(); + for (int i = 0; i < size; i++) { + col.add(getCell(colNum, i)); + } + return col; + } + + @Override + public BinaryBoard copy() { + System.out.println("BinaryBoard copy()"); + BinaryBoard copy = new BinaryBoard(dimension.width, dimension.height); + for (int x = 0; x < this.dimension.width; x++) { + for (int y = 0; y < this.dimension.height; y++) { + copy.setCell(x, y, getCell(x, y).copy()); + } + } + for (PuzzleElement e : modifiedData) { + copy.getPuzzleElement(e).setModifiable(false); + } + return copy; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryCell.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryCell.java new file mode 100644 index 000000000..9007215ad --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryCell.java @@ -0,0 +1,35 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.model.gameboard.GridCell; +import java.awt.Point; + +public class BinaryCell extends GridCell { + public BinaryCell(int valueInt, Point location) { + super(valueInt, location); + } + + public BinaryType getType() { + switch (data) { + case 0: + return BinaryType.ZERO; + case 1: + return BinaryType.ONE; + case 2: + return BinaryType.UNKNOWN; + default: + if (data > 1) { + return BinaryType.UNKNOWN; + } + } + return null; + } + + @Override + public BinaryCell copy() { + BinaryCell copy = new BinaryCell(data, (Point) location.clone()); + copy.setIndex(index); + copy.setModifiable(isModifiable); + copy.setGiven(isGiven); + return copy; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryCellFactory.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryCellFactory.java new file mode 100644 index 000000000..890c26656 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryCellFactory.java @@ -0,0 +1,59 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.ElementFactory; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.save.InvalidFileFormatException; +import java.awt.*; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +public class BinaryCellFactory extends ElementFactory { + + public BinaryCell importCell(Node node, Board board) throws InvalidFileFormatException { + try { + if (!node.getNodeName().equalsIgnoreCase("cell")) { + throw new InvalidFileFormatException( + "binary Factory: unknown puzzleElement puzzleElement"); + } + + BinaryBoard binaryBoard = (BinaryBoard) board; + int width = binaryBoard.getWidth(); + int height = binaryBoard.getHeight(); + + NamedNodeMap attributeList = node.getAttributes(); + int value = Integer.valueOf(attributeList.getNamedItem("value").getNodeValue()); + int x = Integer.valueOf(attributeList.getNamedItem("x").getNodeValue()); + int y = Integer.valueOf(attributeList.getNamedItem("y").getNodeValue()); + + if (x >= width || y >= height) { + throw new InvalidFileFormatException("binary Factory: cell location out of bounds"); + } + if (value < -2) { + throw new InvalidFileFormatException("binary Factory: cell unknown value"); + } + + BinaryCell cell = new BinaryCell(value, new Point(x, y)); + cell.setIndex(y * height + x); + return cell; + } catch (NumberFormatException e) { + throw new InvalidFileFormatException( + "binary Factory: unknown value where integer expected"); + } catch (NullPointerException e) { + throw new InvalidFileFormatException("binary Factory: could not find attribute(s)"); + } + } + + public org.w3c.dom.Element exportCell(Document document, PuzzleElement puzzleElement) { + org.w3c.dom.Element cellElement = document.createElement("cell"); + + BinaryCell cell = (BinaryCell) puzzleElement; + Point loc = cell.getLocation(); + cellElement.setAttribute("value", String.valueOf(cell.getData())); + cellElement.setAttribute("x", String.valueOf(loc.x)); + cellElement.setAttribute("y", String.valueOf(loc.y)); + + return cellElement; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryController.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryController.java new file mode 100644 index 000000000..0bad559d9 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryController.java @@ -0,0 +1,45 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.controller.ElementController; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import java.awt.event.MouseEvent; + +public class BinaryController extends ElementController { + + @Override + public void changeCell(MouseEvent e, PuzzleElement data) { + BinaryCell cell = (BinaryCell) data; + if (e.getButton() == MouseEvent.BUTTON1) { + if (e.isControlDown()) { + this.boardView + .getSelectionPopupMenu() + .show( + boardView, + this.boardView.getCanvas().getX() + e.getX(), + this.boardView.getCanvas().getY() + e.getY()); + } else { + if (cell.getData() == 0) { + data.setData(1); + } else { + if (cell.getData() == 1) { + data.setData(2); + } else { + data.setData(0); + } + } + } + } else { + if (e.getButton() == MouseEvent.BUTTON3) { + if (cell.getData() == 0) { + data.setData(1); + } else { + if (cell.getData() == 1) { + data.setData(2); + } else { + data.setData(0); + } + } + } + } + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryElementView.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryElementView.java new file mode 100644 index 000000000..9ac99c958 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryElementView.java @@ -0,0 +1,120 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.ui.boardview.GridElementView; +import java.awt.*; + +public class BinaryElementView extends GridElementView { + + private static final Font FONT = new Font("TimesRoman", Font.BOLD, 17); + private static final Color FONT_COLOR = Color.BLACK; + + public BinaryElementView(BinaryCell cell) { + super(cell); + } + + /** + * Gets the PuzzleElement associated with this view + * + * @return PuzzleElement associated with this view + */ + @Override + public BinaryCell getPuzzleElement() { + return (BinaryCell) super.getPuzzleElement(); + } + + @Override + public void drawGiven(Graphics2D graphics2D) { + BinaryCell cell = (BinaryCell) puzzleElement; + BinaryType type = cell.getType(); + if (type == BinaryType.ZERO) { + graphics2D.setStroke(new BasicStroke(1)); + graphics2D.setColor(Color.LIGHT_GRAY); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(FONT_COLOR); + graphics2D.setFont(FONT); + FontMetrics metrics = graphics2D.getFontMetrics(FONT); + String value = String.valueOf(puzzleElement.getData()); + int xText = location.x + (size.width - metrics.stringWidth(value)) / 2; + int yText = + location.y + ((size.height - metrics.getHeight()) / 2) + metrics.getAscent(); + graphics2D.drawString(String.valueOf(puzzleElement.getData()), xText, yText); + } else { + if (type == BinaryType.ONE) { + graphics2D.setStroke(new BasicStroke(1)); + graphics2D.setColor(Color.LIGHT_GRAY); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(FONT_COLOR); + graphics2D.setFont(FONT); + FontMetrics metrics = graphics2D.getFontMetrics(FONT); + String value = String.valueOf(puzzleElement.getData()); + int xText = location.x + (size.width - metrics.stringWidth(value)) / 2; + int yText = + location.y + + ((size.height - metrics.getHeight()) / 2) + + metrics.getAscent(); + graphics2D.drawString(String.valueOf(puzzleElement.getData()), xText, yText); + + } else { + if (type == BinaryType.UNKNOWN) { + graphics2D.setStroke(new BasicStroke(0)); + graphics2D.setColor(Color.WHITE); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + } + } + } + } + + @Override + public void drawElement(Graphics2D graphics2D) { + BinaryCell cell = (BinaryCell) puzzleElement; + BinaryType type = cell.getType(); + if (type == BinaryType.ZERO) { + graphics2D.setStroke(new BasicStroke(1)); + graphics2D.setColor(Color.WHITE); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(FONT_COLOR); + graphics2D.setFont(FONT); + FontMetrics metrics = graphics2D.getFontMetrics(FONT); + String value = String.valueOf(puzzleElement.getData()); + int xText = location.x + (size.width - metrics.stringWidth(value)) / 2; + int yText = + location.y + ((size.height - metrics.getHeight()) / 2) + metrics.getAscent(); + graphics2D.drawString(String.valueOf(puzzleElement.getData()), xText, yText); + } else { + if (type == BinaryType.ONE) { + graphics2D.setStroke(new BasicStroke(1)); + graphics2D.setColor(Color.WHITE); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(FONT_COLOR); + graphics2D.setFont(FONT); + FontMetrics metrics = graphics2D.getFontMetrics(FONT); + String value = String.valueOf(puzzleElement.getData()); + int xText = location.x + (size.width - metrics.stringWidth(value)) / 2; + int yText = + location.y + + ((size.height - metrics.getHeight()) / 2) + + metrics.getAscent(); + graphics2D.drawString(String.valueOf(puzzleElement.getData()), xText, yText); + + } else { + if (type == BinaryType.UNKNOWN) { + graphics2D.setStroke(new BasicStroke(0)); + graphics2D.setColor(Color.WHITE); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + } + } + } + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryExporter.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryExporter.java new file mode 100644 index 000000000..cd58314b6 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryExporter.java @@ -0,0 +1,39 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.model.PuzzleExporter; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import org.w3c.dom.Document; + +public class BinaryExporter extends PuzzleExporter { + + public BinaryExporter(Binary binary) { + super(binary); + } + + @Override + protected org.w3c.dom.Element createBoardElement(Document newDocument) { + BinaryBoard board; + if (puzzle.getTree() != null) { + board = (BinaryBoard) puzzle.getTree().getRootNode().getBoard(); + } else { + board = (BinaryBoard) puzzle.getBoardView().getBoard(); + } + + org.w3c.dom.Element boardElement = newDocument.createElement("board"); + boardElement.setAttribute("width", String.valueOf(board.getWidth())); + boardElement.setAttribute("height", String.valueOf(board.getHeight())); + + org.w3c.dom.Element cellsElement = newDocument.createElement("cells"); + for (PuzzleElement puzzleElement : board.getPuzzleElements()) { + BinaryCell cell = (BinaryCell) puzzleElement; + if (cell.getData() != -2) { + org.w3c.dom.Element cellElement = + puzzle.getFactory().exportCell(newDocument, puzzleElement); + cellsElement.appendChild(cellElement); + } + } + + boardElement.appendChild(cellsElement); + return boardElement; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryImporter.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryImporter.java new file mode 100644 index 000000000..2fc5b09ef --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryImporter.java @@ -0,0 +1,117 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.model.PuzzleImporter; +import edu.rpi.legup.save.InvalidFileFormatException; +import java.awt.*; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class BinaryImporter extends PuzzleImporter { + public BinaryImporter(Binary binary) { + super(binary); + } + + @Override + public boolean acceptsRowsAndColumnsInput() { + return true; + } + + @Override + public boolean acceptsTextInput() { + return false; + } + + @Override + public void initializeBoard(int rows, int columns) { + BinaryBoard binaryBoard = new BinaryBoard(columns, rows); + + for (int y = 0; y < rows; y++) { + for (int x = 0; x < columns; x++) { + BinaryCell cell = new BinaryCell(BinaryType.UNKNOWN.toValue(), new Point(x, y)); + cell.setIndex(y * columns + x); + cell.setModifiable(true); + binaryBoard.setCell(x, y, cell); + } + } + puzzle.setCurrentBoard(binaryBoard); + } + + /** + * Creates the board for building + * + * @param node xml document node + * @throws InvalidFileFormatException if file is invalid + */ + @Override + public void initializeBoard(Node node) throws InvalidFileFormatException { + try { + if (!node.getNodeName().equalsIgnoreCase("board")) { + throw new InvalidFileFormatException( + "binary Importer: cannot find board puzzleElement"); + } + Element boardElement = (Element) node; + if (boardElement.getElementsByTagName("cells").getLength() == 0) { + throw new InvalidFileFormatException( + "binary Importer: no puzzleElement found for board"); + } + + Element dataElement = (Element) boardElement.getElementsByTagName("cells").item(0); + NodeList elementDataList = dataElement.getElementsByTagName("cell"); + + BinaryBoard binaryBoard = null; + if (!boardElement.getAttribute("size").isEmpty()) { + int size = Integer.valueOf(boardElement.getAttribute("size")); + binaryBoard = new BinaryBoard(size); + } else { + if (!boardElement.getAttribute("width").isEmpty() + && !boardElement.getAttribute("height").isEmpty()) { + int width = Integer.valueOf(boardElement.getAttribute("width")); + int height = Integer.valueOf(boardElement.getAttribute("height")); + binaryBoard = new BinaryBoard(width, height); + } + } + + int width = binaryBoard.getWidth(); + int height = binaryBoard.getHeight(); + + if (binaryBoard == null || width % 2 != 0 || height % 2 != 0) { + throw new InvalidFileFormatException("binary Importer: invalid board dimensions"); + } + + for (int i = 0; i < elementDataList.getLength(); i++) { + BinaryCell cell = + (BinaryCell) + puzzle.getFactory() + .importCell(elementDataList.item(i), binaryBoard); + Point loc = cell.getLocation(); + if (cell.getData() != BinaryType.UNKNOWN.toValue()) { + cell.setModifiable(false); + cell.setGiven(true); + } + binaryBoard.setCell(loc.x, loc.y, cell); + } + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (binaryBoard.getCell(x, y) == null) { + BinaryCell cell = + new BinaryCell(BinaryType.UNKNOWN.toValue(), new Point(x, y)); + cell.setIndex(y * height + x); + cell.setModifiable(true); + binaryBoard.setCell(x, y, cell); + } + } + } + puzzle.setCurrentBoard(binaryBoard); + } catch (NumberFormatException e) { + throw new InvalidFileFormatException( + "binary Importer: unknown value where integer expected"); + } + } + + @Override + public void initializeBoard(String[] statements) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Binary cannot accept text input"); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryType.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryType.java new file mode 100644 index 000000000..6e3413d7a --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryType.java @@ -0,0 +1,11 @@ +package edu.rpi.legup.puzzle.binary; + +public enum BinaryType { + ZERO, + ONE, + UNKNOWN; + + public int toValue() { + return this.ordinal(); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/BinaryView.java b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryView.java new file mode 100644 index 000000000..b11554f28 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/BinaryView.java @@ -0,0 +1,24 @@ +package edu.rpi.legup.puzzle.binary; + +import edu.rpi.legup.controller.BoardController; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.ui.boardview.GridBoardView; +import java.awt.*; + +public class BinaryView extends GridBoardView { + + public BinaryView(BinaryBoard board) { + super(new BoardController(), new BinaryController(), board.getDimension()); + + for (PuzzleElement puzzleElement : board.getPuzzleElements()) { + BinaryCell cell = (BinaryCell) puzzleElement; + Point loc = cell.getLocation(); + BinaryElementView elementView = new BinaryElementView(cell); + elementView.setIndex(cell.getIndex()); + elementView.setSize(elementSize); + elementView.setLocation( + new Point(loc.x * elementSize.width, loc.y * elementSize.height)); + elementViews.add(elementView); + } + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/elements/BlankTile.java b/src/main/java/edu/rpi/legup/puzzle/binary/elements/BlankTile.java new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/elements/BlankTile.java @@ -0,0 +1 @@ + diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/elements/NumberTile.java b/src/main/java/edu/rpi/legup/puzzle/binary/elements/NumberTile.java new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/elements/NumberTile.java @@ -0,0 +1 @@ + diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java new file mode 100644 index 000000000..e38c6b78d --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java @@ -0,0 +1,55 @@ +package edu.rpi.legup.puzzle.binary.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; +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.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; + +public class CompleteRowColumnDirectRule extends DirectRule { + + public CompleteRowColumnDirectRule() { + super( + "BINA-BASC-0003", + "Complete Row Column", + "If a row/column of length n contains n/2 of a single value, the remaining cells must contain the other value", + "edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png"); + } + + /** + * 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) { + BinaryBoard origBoard = (BinaryBoard) transition.getParents().get(0).getBoard(); + ContradictionRule contraRule = new UnbalancedRowOrColumnContradictionRule(); + BinaryCell binaryCell = (BinaryCell) puzzleElement; + BinaryBoard modified = origBoard.copy(); + BinaryCell c = (BinaryCell) modified.getPuzzleElement(puzzleElement); + + // System.out.println("ORIG" + binaryCell.getData()); + // System.out.println("AFTER" + Math.abs(binaryCell.getData() - 1)); + modified.getPuzzleElement(puzzleElement).setData(binaryCell.getData()); + System.out.println(contraRule.checkContradictionAt(modified, puzzleElement)); + + if (contraRule.checkContradictionAt(modified, puzzleElement) != null) { + return null; + } + + return "Grouping of Three Ones or Zeros not found"; + } + + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java new file mode 100644 index 000000000..8b0d88ae4 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java @@ -0,0 +1,55 @@ +package edu.rpi.legup.puzzle.binary.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; +import edu.rpi.legup.puzzle.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; +import edu.rpi.legup.puzzle.binary.BinaryType; +import java.util.ArrayList; + +public class DuplicateRowsOrColumnsContradictionRule extends ContradictionRule { + private final String NO_CONTRADICTION_MESSAGE = + "Does not contain a contradiction at this index"; + private final String INVALID_USE_MESSAGE = "Row or column must have a value in each cell"; + + public DuplicateRowsOrColumnsContradictionRule() { + super( + "BINA-CONT-0003", + "Duplicate Rows Or Columns", + "There must not be two rows or two columns that are duplicates", + "edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png"); + } + + @Override + public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { + BinaryBoard binaryBoard = (BinaryBoard) board; + BinaryCell cell = (BinaryCell) binaryBoard.getPuzzleElement(puzzleElement); + + ArrayList row = binaryBoard.getRowTypes(cell.getLocation().y); + + int size = row.size(); + + for (int i = 0; i < size; i++) { + if (i > cell.getLocation().y) { + ArrayList currRow = binaryBoard.getRowTypes(i); + if (currRow.equals(row)) { + return null; + } + } + } + + ArrayList col = binaryBoard.getColTypes(cell.getLocation().x); + + for (int i = 0; i < size; i++) { + if (i > cell.getLocation().x) { + ArrayList currCol = binaryBoard.getColTypes(i); + if (currCol.equals(col)) { + return null; + } + } + } + + return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java new file mode 100644 index 000000000..70549cd72 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java @@ -0,0 +1,90 @@ +package edu.rpi.legup.puzzle.binary.rules; + +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.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; +import edu.rpi.legup.puzzle.binary.BinaryType; +import java.util.ArrayList; +import java.util.List; + +public class OneOrZeroCaseRule extends CaseRule { + + public OneOrZeroCaseRule() { + super( + "BINA-CASE-0001", + "One or Zero", + "Each blank cell is either a one or a zero.", + "edu/rpi/legup/images/binary/rules/OneOrZeroCaseRule.png"); + } + + @Override + public String checkRuleRaw(TreeTransition transition) { + List childTransitions = transition.getParents().get(0).getChildren(); + if (childTransitions.size() != 2) { + return super.getInvalidUseOfRuleMessage() + ": 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 super.getInvalidUseOfRuleMessage() + + ": This case rule must have 1 modified cell for each case."; + } + + BinaryCell mod1 = (BinaryCell) case1.getBoard().getModifiedData().iterator().next(); + BinaryCell mod2 = (BinaryCell) case2.getBoard().getModifiedData().iterator().next(); + if (!mod1.getLocation().equals(mod2.getLocation())) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must modify the same cell for each case."; + } + + if (!((mod1.getType() == BinaryType.ZERO && mod2.getType() == BinaryType.ONE) + || (mod2.getType() == BinaryType.ZERO && mod1.getType() == BinaryType.ONE))) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must an empty white and black cell."; + } + + return null; + } + + @Override + public CaseBoard getCaseBoard(Board board) { + BinaryBoard binaryBoard = (BinaryBoard) board.copy(); + CaseBoard caseBoard = new CaseBoard(binaryBoard, this); + binaryBoard.setModifiable(false); + for (PuzzleElement element : binaryBoard.getPuzzleElements()) { + if (((BinaryCell) element).getType() == BinaryType.UNKNOWN) { + caseBoard.addPickableElement(element); + } + } + return caseBoard; + } + + @Override + public ArrayList getCases(Board board, PuzzleElement puzzleElement) { + ArrayList cases = new ArrayList<>(); + Board case1 = board.copy(); + PuzzleElement data1 = case1.getPuzzleElement(puzzleElement); + data1.setData(BinaryType.ZERO.toValue()); + case1.addModifiedData(data1); + cases.add(case1); + + Board case2 = board.copy(); + PuzzleElement data2 = case2.getPuzzleElement(puzzleElement); + data2.setData(BinaryType.ONE.toValue()); + case2.addModifiedData(data2); + cases.add(case2); + + return cases; + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + return null; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneTileGapDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneTileGapDirectRule.java new file mode 100644 index 000000000..2e1e96fa5 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneTileGapDirectRule.java @@ -0,0 +1,64 @@ +package edu.rpi.legup.puzzle.binary.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; +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.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; + +public class OneTileGapDirectRule extends DirectRule { + private final String INVALID_USE_MESSAGE = "Number at cell is incorrect"; + + public OneTileGapDirectRule() { + super( + "BINA-BASC-0002", + "One Tile Gap", + "If an empty tile is in between the same value, fill the gap with the other value.", + "edu/rpi/legup/images/binary/rules/OneTileGapDirectRule.png"); + } + + boolean checkLeftRight(BinaryCell c, BinaryBoard board) { + int x = c.getLocation().x; + int y = c.getLocation().y; + return board.getCell(x - 1, y).getType() != c.getType() + || board.getCell(x + 1, y).getType() != c.getType(); + } + + boolean checkUpDown(BinaryCell c, BinaryBoard board) { + int x = c.getLocation().x; + int y = c.getLocation().y; + return board.getCell(x, y - 1).getType() != c.getType() + || board.getCell(x, y + 1).getType() != c.getType(); + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + BinaryBoard origBoard = (BinaryBoard) transition.getParents().get(0).getBoard(); + ContradictionRule contraRule = new ThreeAdjacentContradictionRule(); + BinaryCell binaryCell = (BinaryCell) puzzleElement; + BinaryBoard modified = origBoard.copy(); + + // System.out.println("ORIG" + binaryCell.getData()); + // System.out.println("AFTER" + Math.abs(binaryCell.getData() - 1)); + modified.getPuzzleElement(puzzleElement).setData(Math.abs(binaryCell.getData() - 1)); + + PuzzleElement newP = binaryCell; + + System.out.println(contraRule.checkContradictionAt(modified, newP)); + + if (contraRule.checkContradictionAt(modified, newP) == null) { + return null; + } + modified.getPuzzleElement(puzzleElement).setData(Math.abs(binaryCell.getData() - 1)); + + return "Grouping of Three Ones or Zeros not found"; + } + + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/SurroundPairDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/SurroundPairDirectRule.java new file mode 100644 index 000000000..dc2f07c8b --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/SurroundPairDirectRule.java @@ -0,0 +1,48 @@ +package edu.rpi.legup.puzzle.binary.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; +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.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; + +public class SurroundPairDirectRule extends DirectRule { + + public SurroundPairDirectRule() { + super( + "BINA-BASC-0001", + "Surround Pair", + "If two adjacent tiles have the same value, surround the tiles with the other value.", + "edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png"); + } + + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + BinaryBoard origBoard = (BinaryBoard) transition.getParents().get(0).getBoard(); + ContradictionRule contraRule = new ThreeAdjacentContradictionRule(); + BinaryCell binaryCell = (BinaryCell) puzzleElement; + BinaryBoard modified = origBoard.copy(); + + // System.out.println("ORIG" + binaryCell.getData()); + // System.out.println("AFTER" + Math.abs(binaryCell.getData() - 1)); + modified.getPuzzleElement(puzzleElement).setData(Math.abs(binaryCell.getData() - 1)); + + PuzzleElement newP = binaryCell; + + System.out.println(contraRule.checkContradictionAt(modified, newP)); + + if (contraRule.checkContradictionAt(modified, newP) == null) { + return null; + } + modified.getPuzzleElement(puzzleElement).setData(Math.abs(binaryCell.getData() - 1)); + + return "Grouping of Three Ones or Zeros not found"; + } + + @Override + public Board getDefaultBoard(TreeNode node) { + return null; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/ThreeAdjacentContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/ThreeAdjacentContradictionRule.java new file mode 100644 index 000000000..075642246 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/ThreeAdjacentContradictionRule.java @@ -0,0 +1,127 @@ +package edu.rpi.legup.puzzle.binary.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; +import edu.rpi.legup.puzzle.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; +import edu.rpi.legup.puzzle.binary.BinaryType; + +public class ThreeAdjacentContradictionRule extends ContradictionRule { + private final String NO_CONTRADICTION_MESSAGE = + "Does not contain a contradiction at this index"; + private final String INVALID_USE_MESSAGE = "Contradiction must be a zero or one"; + + public ThreeAdjacentContradictionRule() { + super( + "BINA-CONT-0001", + "Three Adjacent", + "There must not be three adjacent zeros or three adjacent ones in a row or column", + "edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png"); + } + + @Override + public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { + BinaryBoard binaryBoard = (BinaryBoard) board; + int height = binaryBoard.getHeight(); + int width = binaryBoard.getWidth(); + + BinaryCell cell = (BinaryCell) binaryBoard.getPuzzleElement(puzzleElement); + System.out.println("THE CELL IS : " + cell.getType()); + int cellX = cell.getLocation().x; + int cellY = cell.getLocation().y; + BinaryCell oneUp = null; + BinaryCell oneDown = null; + BinaryCell oneForward = null; + BinaryCell oneBackward = null; + BinaryCell twoUp = null; + BinaryCell twoDown = null; + BinaryCell twoForward = null; + BinaryCell twoBackward = null; + if (binaryBoard.getCell(cellX, cellY + 1) != null) { + oneUp = binaryBoard.getCell(cellX, cellY + 1); + } + if (binaryBoard.getCell(cellX, cellY - 1) != null) { + oneDown = binaryBoard.getCell(cellX, cellY - 1); + } + if (binaryBoard.getCell(cellX + 1, cellY) != null) { + oneForward = binaryBoard.getCell(cellX + 1, cellY); + } + if (binaryBoard.getCell(cellX - 1, cellY) != null) { + oneBackward = binaryBoard.getCell(cellX - 1, cellY); + } + if (binaryBoard.getCell(cellX, cellY + 2) != null) { + twoUp = binaryBoard.getCell(cellX, cellY + 2); + } + if (binaryBoard.getCell(cellX, cellY - 2) != null) { + twoDown = binaryBoard.getCell(cellX, cellY - 2); + } + if (binaryBoard.getCell(cellX + 2, cellY) != null) { + twoForward = binaryBoard.getCell(cellX + 2, cellY); + } + if (binaryBoard.getCell(cellX - 2, cellY) != null) { + twoBackward = binaryBoard.getCell(cellX - 2, cellY); + } + + if (cell.getType() == BinaryType.ONE || cell.getType() == BinaryType.ZERO) { + if (twoBackward != null + && oneBackward != null + && twoBackward.getType() != BinaryType.UNKNOWN + && oneBackward.getType() != BinaryType.UNKNOWN) { + if (twoBackward.getType() == cell.getType() + && oneBackward.getType() == cell.getType()) { + System.out.println("1"); + return null; + } + } + if (twoForward != null + && oneForward != null + && twoForward.getType() != BinaryType.UNKNOWN + && oneForward.getType() != BinaryType.UNKNOWN) { + if (twoForward.getType() == cell.getType() + && oneForward.getType() == cell.getType()) { + System.out.println("2"); + return null; + } + } + if (twoDown != null + && oneDown != null + && twoDown.getType() != BinaryType.UNKNOWN + && oneDown.getType() != BinaryType.UNKNOWN) { + if (twoDown.getType() == cell.getType() && oneDown.getType() == cell.getType()) { + System.out.println("3"); + return null; + } + } + if (twoUp != null + && oneUp != null + && twoUp.getType() != BinaryType.UNKNOWN + && oneUp.getType() != BinaryType.UNKNOWN) { + if (twoUp.getType() == cell.getType() && oneUp.getType() == cell.getType()) { + System.out.println("4"); + return null; + } + } + if (oneBackward != null + && oneForward != null + && oneBackward.getType() != BinaryType.UNKNOWN + && oneForward.getType() != BinaryType.UNKNOWN) { + if (oneBackward.getType() == cell.getType() + && oneForward.getType() == cell.getType()) { + System.out.println("5"); + return null; + } + } + if (oneUp != null + && oneDown != null + && oneUp.getType() != BinaryType.UNKNOWN + && oneDown.getType() != BinaryType.UNKNOWN) { + if (oneUp.getType() == cell.getType() && oneDown.getType() == cell.getType()) { + System.out.println("6"); + return null; + } + } + } + return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java new file mode 100644 index 000000000..5089b3b5f --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java @@ -0,0 +1,68 @@ +package edu.rpi.legup.puzzle.binary.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; +import edu.rpi.legup.puzzle.binary.BinaryBoard; +import edu.rpi.legup.puzzle.binary.BinaryCell; +import edu.rpi.legup.puzzle.binary.BinaryType; +import java.util.Set; + +public class UnbalancedRowOrColumnContradictionRule extends ContradictionRule { + + private final String NO_CONTRADICTION_MESSAGE = + "Does not contain a contradiction at this index"; + private final String INVALID_USE_MESSAGE = "Row or column must have a value in each cell"; + + public UnbalancedRowOrColumnContradictionRule() { + super( + "BINA-CONT-0002", + "Unbalanced Row Or Column", + "Each row or column must contain an equal number of zeros and ones", + "edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png"); + } + + @Override + public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { + BinaryBoard binaryBoard = (BinaryBoard) board; + + BinaryCell cell = (BinaryCell) binaryBoard.getPuzzleElement(puzzleElement); + Set row = binaryBoard.getRowCells(cell.getLocation().y); + + int size = row.size(); + int rowNumZeros = 0; + int rowNumOnes = 0; + + for (BinaryCell item : row) { + if (item.getType() == BinaryType.ZERO) { + rowNumZeros++; + } else if (item.getType() == BinaryType.ONE) { + rowNumOnes++; + } + } + + if (rowNumZeros == size / 2 && rowNumOnes == size / 2) { + return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + } + + Set col = binaryBoard.getCol(cell.getLocation().x); + + size = col.size(); + int colNumZeros = 0; + int colNumOnes = 0; + + for (BinaryCell item : col) { + if (item.getType() == BinaryType.ZERO) { + colNumZeros++; + } else if (item.getType() == BinaryType.ONE) { + colNumOnes++; + } + } + + if (colNumZeros == size / 2 && colNumOnes == size / 2) { + return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + } + + return null; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/binary_reference_sheet.txt b/src/main/java/edu/rpi/legup/puzzle/binary/rules/binary_reference_sheet.txt new file mode 100644 index 000000000..c8cb0d1b9 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/binary_reference_sheet.txt @@ -0,0 +1,9 @@ +BINA-BASC-0001 : SurroundPairDirectRule +BINA-BASC-0002 : OneTileGapDirectRule +BINA-BASC-0003 : CompleteRowColumnDirectRule + +BINA-CONT-0001 : ThreeAdjacentContradictionRule +BINA-CONT-0002 : UnbalancedRowOrColumnContradictionRule +BINA-CONT-0003 : DuplicateRowsOrColumnsContradictionRule + +BINA-CASE-0001 : OneOrZeroCaseRule \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattle.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattle.java index 760fa88b2..39092bbc6 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattle.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattle.java @@ -1,4 +1,5 @@ package edu.rpi.legup.puzzle.starbattle; + import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.gameboard.Board; @@ -30,6 +31,5 @@ public boolean isBoardComplete(Board board) { } @Override - public void onBoardChange(Board board) { - } + public void onBoardChange(Board board) {} } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleBoard.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleBoard.java index 2c4a20ebc..5132f33e4 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleBoard.java @@ -1,16 +1,16 @@ package edu.rpi.legup.puzzle.starbattle; -import java.util.*; - import edu.rpi.legup.model.gameboard.GridBoard; import edu.rpi.legup.model.gameboard.PuzzleElement; +import java.util.*; public class StarBattleBoard extends GridBoard { private int size; private int puzzleNum; protected List regions; - //private ArrayList groupSizes; + + // private ArrayList groupSizes; public StarBattleBoard(int size, int num) { super(size, size); @@ -24,10 +24,10 @@ public StarBattleBoard(int size, int num) { @Override public StarBattleCell getCell(int x, int y) { - return (StarBattleCell) super.getCell(x,y); + return (StarBattleCell) super.getCell(x, y); } - /* + /* public StarBattleCell getCell(int groupIndex, int x, int y) { return getCell(x + (groupIndex % groupSize) * groupSize, y + (groupIndex / groupSize) * groupSize); }*/ @@ -44,7 +44,9 @@ public Set getRow(int rowNum) { return row; } - public int getPuzzleNumber() { return puzzleNum; } + public int getPuzzleNumber() { + return puzzleNum; + } public Set getCol(int colNum) { Set column = new HashSet<>(); @@ -72,7 +74,7 @@ public void setRegion(int regionNum, StarBattleRegion region) { public int columnStars(int columnIndex) { int stars = 0; if (columnIndex < size) { - for (StarBattleCell c: this.getCol(columnIndex)) { + for (StarBattleCell c : this.getCol(columnIndex)) { if (c.getType() == StarBattleCellType.STAR) { ++stars; } @@ -84,7 +86,7 @@ public int columnStars(int columnIndex) { public int rowStars(int rowIndex) { int stars = 0; if (rowIndex < size) { - for (StarBattleCell c: this.getRow(rowIndex)) { + for (StarBattleCell c : this.getRow(rowIndex)) { if (c.getType() == StarBattleCellType.STAR) { ++stars; } @@ -109,5 +111,3 @@ public StarBattleBoard copy() { return copy; } } - - diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCell.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCell.java index a316872d9..ddae8f882 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCell.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCell.java @@ -2,7 +2,6 @@ import edu.rpi.legup.model.elements.Element; import edu.rpi.legup.model.gameboard.GridCell; - import java.awt.*; import java.awt.event.MouseEvent; @@ -13,10 +12,10 @@ public class StarBattleCell extends GridCell { /** * StarBattleCell Constructor - creates a new StarBattle cell to hold the puzzleElement * - * @param value value of the star battle cell denoting its state - * @param location location of the cell on the board + * @param value value of the star battle cell denoting its state + * @param location location of the cell on the board * @param groupIndex indicates what group # the cell is in. - * @param size size of the star battle cell + * @param size size of the star battle cell */ public StarBattleCell(int value, Point location, int groupIndex, int size) { super(value, location); @@ -24,7 +23,9 @@ public StarBattleCell(int value, Point location, int groupIndex, int size) { this.max = size; } - public int getGroupIndex() { return groupIndex; } + public int getGroupIndex() { + return groupIndex; + } @Override public void setType(Element e, MouseEvent m) { @@ -38,27 +39,25 @@ public void setType(Element e, MouseEvent m) { case "STBL-PLAC-0003": this.data = -1; break; - - case "STBL-UNPL-0001"://Not sure how button events work - switch (m.getButton()){ + + case "STBL-UNPL-0001": // Not sure how button events work + switch (m.getButton()) { case MouseEvent.BUTTON1: if (this.data > 0 || this.data < -3) { this.data = -3; - } - else { + } else { this.data = this.data + 1; } break; case MouseEvent.BUTTON3: if (this.data > -4) { this.data = this.data - 1; - } - else { - this.data = -1;//Unsure + } else { + this.data = -1; // Unsure } break; } - break; + break; } } @@ -85,4 +84,4 @@ public StarBattleCell copy() { copy.setGiven(isGiven); return copy; } -} \ No newline at end of file +} diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellFactory.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellFactory.java index 9f7fd0fee..eb2a830f6 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellFactory.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellFactory.java @@ -1,20 +1,21 @@ package edu.rpi.legup.puzzle.starbattle; + import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.ElementFactory; import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.save.InvalidFileFormatException; +import java.awt.*; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; -import java.awt.*; - public class StarBattleCellFactory extends ElementFactory { @Override public StarBattleCell importCell(Node node, Board board) throws InvalidFileFormatException { try { if (!node.getNodeName().equalsIgnoreCase("cell")) { - throw new InvalidFileFormatException("starbattle Factory: unknown puzzleElement puzzleElement"); + throw new InvalidFileFormatException( + "starbattle Factory: unknown puzzleElement puzzleElement"); } StarBattleBoard starbattleBoard = (StarBattleBoard) board; @@ -24,28 +25,27 @@ public StarBattleCell importCell(Node node, Board board) throws InvalidFileForma int value = Integer.valueOf(attributeList.getNamedItem("value").getNodeValue()); int x = Integer.valueOf(attributeList.getNamedItem("x").getNodeValue()); int y = Integer.valueOf(attributeList.getNamedItem("y").getNodeValue()); - int groupIndex = Integer.valueOf(attributeList.getNamedItem("groupIndex").getNodeValue()); + int groupIndex = + Integer.valueOf(attributeList.getNamedItem("groupIndex").getNodeValue()); if (x >= size || y >= size) { - throw new InvalidFileFormatException("starbattle Factory: cell location out of bounds"); + throw new InvalidFileFormatException( + "starbattle Factory: cell location out of bounds"); } if (groupIndex >= size || groupIndex < 0) { throw new InvalidFileFormatException("starbattle Factory: not in a valid region"); } - if (value != 0) { //ALL INITIAL PUZZLES ARE BLANK, SUBJECT TO CHANGE + if (value != 0) { // ALL INITIAL PUZZLES ARE BLANK, SUBJECT TO CHANGE throw new InvalidFileFormatException("starbattle Factory: cell unknown value"); } StarBattleCell cell = new StarBattleCell(value, new Point(x, y), groupIndex, size); cell.setIndex(y * size + x); return cell; - } - - catch (NumberFormatException e1) { + } catch (NumberFormatException e1) { e1.printStackTrace(); - throw new InvalidFileFormatException("starbattle Factory: unknown value where integer expected"); - } - - catch (NullPointerException e2) { + throw new InvalidFileFormatException( + "starbattle Factory: unknown value where integer expected"); + } catch (NullPointerException e2) { e2.printStackTrace(); throw new InvalidFileFormatException("starbattle Factory: could not find attribute(s)"); } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellType.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellType.java index 565f608d7..e48e46fcb 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellType.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleCellType.java @@ -1,12 +1,14 @@ -//StarBattleCellType.java +// StarBattleCellType.java package edu.rpi.legup.puzzle.starbattle; public enum StarBattleCellType { - STAR(-2), BLACK(-1), UNKNOWN(0); + STAR(-2), + BLACK(-1), + UNKNOWN(0); - public int value; + public int value; StarBattleCellType(int value) { this.value = value; } -} \ No newline at end of file +} diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleController.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleController.java index 4ebeb39ba..ba19361c9 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleController.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleController.java @@ -2,7 +2,6 @@ import edu.rpi.legup.controller.ElementController; import edu.rpi.legup.model.gameboard.PuzzleElement; - import java.awt.event.MouseEvent; public class StarBattleController extends ElementController { @@ -11,23 +10,24 @@ public void changeCell(MouseEvent e, PuzzleElement data) { StarBattleCell cell = (StarBattleCell) data; if (e.getButton() == MouseEvent.BUTTON1) { if (e.isControlDown()) { - this.boardView.getSelectionPopupMenu().show(boardView, this.boardView.getCanvas().getX() + e.getX(), this.boardView.getCanvas().getY() + e.getY()); - } - else { + this.boardView + .getSelectionPopupMenu() + .show( + boardView, + this.boardView.getCanvas().getX() + e.getX(), + this.boardView.getCanvas().getY() + e.getY()); + } else { if (cell.getData() >= 0) { data.setData(-2); - } - else { + } else { data.setData(cell.getData() + 1); } } - } - else { + } else { if (e.getButton() == MouseEvent.BUTTON3) { if (cell.getData() == -2) { data.setData(0); - } - else { + } else { data.setData(cell.getData() - 1); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleElementView.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleElementView.java index ff5d54d1c..66d59d364 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleElementView.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleElementView.java @@ -1,7 +1,6 @@ package edu.rpi.legup.puzzle.starbattle; import edu.rpi.legup.ui.boardview.GridElementView; - import java.awt.*; public class StarBattleElementView extends GridElementView { @@ -22,7 +21,14 @@ public void drawElement(Graphics2D graphics2D) { if (type == StarBattleCellType.STAR) { graphics2D.setColor(Color.LIGHT_GRAY); graphics2D.fillRect(location.x, location.y, size.width, size.height); - graphics2D.drawImage(StarBattleView.STAR, location.x, location.y, size.width, size.height, Color.WHITE, null); + graphics2D.drawImage( + StarBattleView.STAR, + location.x, + location.y, + size.width, + size.height, + Color.WHITE, + null); graphics2D.setColor(Color.BLACK); graphics2D.drawRect(location.x, location.y, size.width, size.height); } else if (type == StarBattleCellType.BLACK) { @@ -36,6 +42,5 @@ public void drawElement(Graphics2D graphics2D) { graphics2D.setColor(Color.BLACK); graphics2D.drawRect(location.x, location.y, size.width, size.height); } - } } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleExporter.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleExporter.java index 58fb41e63..f2d2c4d80 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleExporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleExporter.java @@ -1,7 +1,6 @@ package edu.rpi.legup.puzzle.starbattle; import edu.rpi.legup.model.PuzzleExporter; - import org.w3c.dom.Document; public class StarBattleExporter extends PuzzleExporter { @@ -20,14 +19,15 @@ protected org.w3c.dom.Element createBoardElement(Document newDocument) { org.w3c.dom.Element cellsElement = newDocument.createElement("cells"); for (StarBattleCell cell : sb_region.getCells()) { if (cell.getData() == 0) { - org.w3c.dom.Element cellElement = puzzle.getFactory().exportCell(newDocument, cell); + org.w3c.dom.Element cellElement = + puzzle.getFactory().exportCell(newDocument, cell); cellsElement.appendChild(cellElement); } regionsElement.appendChild(cellsElement); } boardElement.appendChild(regionsElement); } - + return boardElement; } } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleImporter.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleImporter.java index fa0e065ee..2a608c893 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleImporter.java @@ -2,37 +2,32 @@ import edu.rpi.legup.model.PuzzleImporter; import edu.rpi.legup.save.InvalidFileFormatException; +import java.awt.Point; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import java.awt.Point; +public class StarBattleImporter extends PuzzleImporter { -public class StarBattleImporter extends PuzzleImporter{ - - public StarBattleImporter(StarBattle starbattle) { super(starbattle); } - /** - * Puzzle setting to support row and column inputs - */ + /** Puzzle setting to support row and column inputs */ @Override public boolean acceptsRowsAndColumnsInput() { return true; } - /** - * Puzzle setting to disable support for text input - */ + /** Puzzle setting to disable support for text input */ @Override public boolean acceptsTextInput() { return false; } - /** + /** * Constructs empty StarBattle gameboard as per the provided dimensions + * * @param rows number of rows and columns for the gameboard */ @Override @@ -44,6 +39,7 @@ public void initializeBoard(int rows, int columns) { /** * Constructs StarBattle gameboard + * * @param node xml document node * @throws InvalidFileFormatException if file is invalid */ @@ -54,10 +50,13 @@ public void initializeBoard(Node node) throws InvalidFileFormatException { NodeList regionNodes = puzzleElement.getElementsByTagName("region"); int size = Integer.parseInt(puzzleElement.getAttribute("size")); if (regionNodes.getLength() != size) { - throw new InvalidFileFormatException("Not the current amount of regions in the puzzle."); + throw new InvalidFileFormatException( + "Not the current amount of regions in the puzzle."); } - StarBattleBoard StarBattleBoard = new StarBattleBoard(size, puzzle_num); // Initialize the board with width and height from XML + StarBattleBoard StarBattleBoard = + new StarBattleBoard( + size, puzzle_num); // Initialize the board with width and height from XML for (int i = 0; i < regionNodes.getLength(); i++) { Element regionElement = (Element) regionNodes.item(i); @@ -87,10 +86,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException { puzzle.setCurrentBoard(StarBattleBoard); } - - /** * Initialize board via string of statements. + * * @throws UnsupportedOperationException since StarBattle does not support text input */ @Override @@ -98,6 +96,3 @@ public void initializeBoard(String[] statements) throws UnsupportedOperationExce throw new UnsupportedOperationException("Star Battle does not accept text input"); } } - - - diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleRegion.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleRegion.java index 730f9291f..b35d80655 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleRegion.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleRegion.java @@ -2,14 +2,14 @@ import edu.rpi.legup.model.gameboard.GridRegion; -public class StarBattleRegion extends GridRegion{ +public class StarBattleRegion extends GridRegion { public StarBattleRegion() { super(); } public StarBattleRegion copy() { StarBattleRegion copy = new StarBattleRegion(); - for (StarBattleCell c: regionCells) { + for (StarBattleCell c : regionCells) { copy.addCell(c.copy()); } return copy; @@ -17,7 +17,7 @@ public StarBattleRegion copy() { public int numStars() { int stars = 0; - for (StarBattleCell c: regionCells) { + for (StarBattleCell c : regionCells) { if (c.getType() == StarBattleCellType.STAR) { ++stars; } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleView.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleView.java index ceb0eec19..550b5495d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleView.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/StarBattleView.java @@ -1,26 +1,22 @@ package edu.rpi.legup.puzzle.starbattle; -import java.io.IOException; - -import javax.imageio.ImageIO; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import edu.rpi.legup.puzzle.starbattle.StarBattleView; -import edu.rpi.legup.ui.boardview.GridBoardView; - import edu.rpi.legup.controller.BoardController; import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.ui.boardview.GridBoardView; import java.awt.*; +import java.io.IOException; +import javax.imageio.ImageIO; public class StarBattleView extends GridBoardView { static Image STAR; static { try { - STAR = ImageIO.read(ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/starbattle/star.gif")); - } - catch (IOException e) { + STAR = + ImageIO.read( + ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/starbattle/star.gif")); + } catch (IOException e) { // pass } } @@ -34,10 +30,9 @@ public StarBattleView(StarBattleBoard board) { StarBattleElementView elementView = new StarBattleElementView(cell); elementView.setIndex(cell.getIndex()); elementView.setSize(elementSize); - elementView.setLocation(new Point(loc.x * elementSize.width, loc.y * elementSize.height)); + elementView.setLocation( + new Point(loc.x * elementSize.width, loc.y * elementSize.height)); elementViews.add(elementView); } } - - } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/BlackTile.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/BlackTile.java index 2601bd351..99f42886e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/BlackTile.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/BlackTile.java @@ -4,6 +4,10 @@ public class BlackTile extends NonPlaceableElement { public BlackTile() { - super("STBL-PLAC-0002", "Black Tile", "The black tile that shows where you cannot place a star", "edu/rpi/legup/images/lightup/black.gif"); + super( + "STBL-PLAC-0002", + "Black Tile", + "The black tile that shows where you cannot place a star", + "edu/rpi/legup/images/lightup/black.gif"); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/StarTile.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/StarTile.java index d42cc0010..13ada3f4d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/StarTile.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/StarTile.java @@ -4,6 +4,10 @@ public class StarTile extends NonPlaceableElement { public StarTile() { - super("STBL-PLAC-0001", "Star Tile", "The star tile, the token of the game.", "edu/rpi/legup/images/starbattle/star.gif"); + super( + "STBL-PLAC-0001", + "Star Tile", + "The star tile, the token of the game.", + "edu/rpi/legup/images/starbattle/star.gif"); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/UnknownTile.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/UnknownTile.java index c2459f642..425fb5d5e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/UnknownTile.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/UnknownTile.java @@ -4,6 +4,10 @@ public class UnknownTile extends NonPlaceableElement { public UnknownTile() { - super("STBL-UNPL-0001", "Unknown Tile", "An empty tile", "edu/rpi/legup/images/starbattle/star.gif"); + super( + "STBL-UNPL-0001", + "Unknown Tile", + "An empty tile", + "edu/rpi/legup/images/starbattle/star.gif"); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/WhiteTile.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/WhiteTile.java index a064c1fad..2227eb37a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/WhiteTile.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/elements/WhiteTile.java @@ -4,7 +4,10 @@ public class WhiteTile extends PlaceableElement { public WhiteTile() { - super("STBL-PLAC-0001", "White Tile", "The white tile", "edu/rpi/legup/images/starbattle/white.gif"); + super( + "STBL-PLAC-0001", + "White Tile", + "The white tile", + "edu/rpi/legup/images/starbattle/white.gif"); } } - diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/BlackoutDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/BlackoutDirectRule.java index 75fbaadb6..2ab66cf93 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/BlackoutDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/BlackoutDirectRule.java @@ -13,20 +13,21 @@ public class BlackoutDirectRule extends DirectRule { public BlackoutDirectRule() { - super("STBL-BASC-0001", + super( + "STBL-BASC-0001", "Blackout", "If a row, column, or region has enough stars, its unknown spaces are black.", "edu/rpi/legup/images/starbattle/rules/BlackOutDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { @@ -50,7 +51,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 @@ -60,5 +62,3 @@ public Board getDefaultBoard(TreeNode node) { return null; } } - - diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ClashingOrbitContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ClashingOrbitContradictionRule.java index 0ca27ab4a..88f0072e5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ClashingOrbitContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ClashingOrbitContradictionRule.java @@ -3,30 +3,29 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; 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.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; - import java.awt.*; public class ClashingOrbitContradictionRule extends ContradictionRule { public ClashingOrbitContradictionRule() { - super("STBL-CONT-0003", + super( + "STBL-CONT-0003", "Clashing Orbit", "No two stars can be adjacent to each other.", "edu/rpi/legup/images/starbattle/contradictions/ClashingOrbitContradictionRule.png"); } /** - * Checks whether the transition has a contradiction at the specific puzzleElement index using this rule + * Checks whether the transition has a contradiction at the specific puzzleElement index using + * this rule * - * @param board board to check contradiction + * @param board board to check contradiction * @param puzzleElement equivalent puzzleElement * @return null if the transition contains a contradiction at the specified puzzleElement, - * otherwise error message + * otherwise error message */ @Override public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { @@ -41,15 +40,15 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { // check neighboring cells for a star Point location = cell.getLocation(); - int rowStart = Math.max( location.x - 1, 0 ); - int rowEnd = Math.min( location.x + 1, starbattleBoard.getSize() - 1 ); - int colStart = Math.max( location.y - 1, 0 ); - int colEnd = Math.min( location.y + 1, starbattleBoard.getSize() - 1 ); + int rowStart = Math.max(location.x - 1, 0); + int rowEnd = Math.min(location.x + 1, starbattleBoard.getSize() - 1); + int colStart = Math.max(location.y - 1, 0); + int colEnd = Math.min(location.y + 1, starbattleBoard.getSize() - 1); for (int row = rowStart; row <= rowEnd; row++) { for (int col = colStart; col <= colEnd; col++) { if (starbattleBoard.getCell(row, col).getType() == StarBattleCellType.STAR - && (row != location.x || col != location.y)) { + && (row != location.x || col != location.y)) { return null; } } @@ -57,4 +56,4 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { return super.getNoContradictionMessage(); } -} \ No newline at end of file +} diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRegionsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRegionsDirectRule.java index b42bfd1c0..433567460 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRegionsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRegionsDirectRule.java @@ -1,7 +1,6 @@ package edu.rpi.legup.puzzle.starbattle.rules; import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.gameboard.GridRegion; import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.rules.DirectRule; import edu.rpi.legup.model.tree.TreeNode; @@ -9,41 +8,41 @@ import edu.rpi.legup.puzzle.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; - import java.util.HashSet; import java.util.Set; public class ColumnsWithinRegionsDirectRule extends DirectRule { public ColumnsWithinRegionsDirectRule() { - super("STBL-BASC-0002", + super( + "STBL-BASC-0002", "Columns Within Regions", "If a number of columns is fully contained by a number of regions with an equal number of missing stars, spaces of other columns in those regions must be black.", "edu/rpi/legup/images/starbattle/rules/ColumnsWithinRegionsDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { - //assumption: the rule has been applied to its fullest extent and the rows and regions - //are now mutually encompassing + // assumption: the rule has been applied to its fullest extent and the rows and regions + // are now mutually encompassing StarBattleBoard board = (StarBattleBoard) transition.getBoard(); StarBattleCell cell = (StarBattleCell) board.getPuzzleElement(puzzleElement); if (cell.getType() != StarBattleCellType.BLACK) { return "Only black cells are allowed for this rule!"; } - //the columns that are contained + // the columns that are contained Set columns = new HashSet(); - //the regions that contain them + // the regions that contain them Set regions = new HashSet(); - //columns and regions to process + // columns and regions to process Set columnsToCheck = new HashSet(); Set regionsToCheck = new HashSet(); int columnStars = 0; @@ -52,9 +51,9 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem regionsToCheck.add(cell.getGroupIndex()); while (!columnsToCheck.isEmpty() || !regionsToCheck.isEmpty()) { - for (int r: regionsToCheck) { + for (int r : regionsToCheck) { regionStars += board.getRegion(r).numStars(); - for (PuzzleElement c: board.getRegion(r).getCells()) { + for (PuzzleElement c : board.getRegion(r).getCells()) { int column = ((StarBattleCell) c).getLocation().x; if (columns.add(column)) { columnsToCheck.add(column); @@ -62,10 +61,10 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } regionsToCheck.remove(r); } - for (int c: columnsToCheck) { + for (int c : columnsToCheck) { columnStars += board.columnStars(c); for (int i = 0; i < board.getSize(); ++i) { - int region = board.getCell(c,i).getGroupIndex(); + int region = board.getCell(c, i).getGroupIndex(); if (regions.add(region)) { regionsToCheck.add(region); } @@ -74,14 +73,16 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } } // are the columns and regions missing an equal amount of stars - if (board.getPuzzleNumber() * columns.size() - columnStars != board.getPuzzleNumber() * regions.size() - regionStars) { + if (board.getPuzzleNumber() * columns.size() - columnStars + != board.getPuzzleNumber() * regions.size() - regionStars) { return "The number of missing stars in the columns and regions must be equal and every extraneous cell must be black!"; } return null; } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRowsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRowsDirectRule.java index 0a78c8868..5d108a0cd 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRowsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/ColumnsWithinRowsDirectRule.java @@ -8,44 +8,44 @@ import edu.rpi.legup.puzzle.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; - import java.util.HashSet; import java.util.Set; public class ColumnsWithinRowsDirectRule extends DirectRule { public ColumnsWithinRowsDirectRule() { - super("STBL-BASC-0003", + super( + "STBL-BASC-0003", "Columns Within Rows", "If a number of columns is fully contained by a number of rows with an equal number of missing stars, spaces of other columns in those rows must be black.", "edu/rpi/legup/images/starbattle/rules/ColumnsWithinRowsDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { - //assumption: the rule has been applied to its fullest extent and the rows and columns - //are now mutually encompassing + // assumption: the rule has been applied to its fullest extent and the rows and columns + // are now mutually encompassing StarBattleBoard board = (StarBattleBoard) transition.getBoard(); StarBattleCell cell = (StarBattleCell) board.getPuzzleElement(puzzleElement); if (cell.getType() != StarBattleCellType.BLACK) { return "Only black cells are allowed for this rule!"; } - //the columns that are contained + // the columns that are contained Set columns = new HashSet(); - //the rows that contain them + // the rows that contain them Set rows = new HashSet(); - //columns and rows to process + // columns and rows to process Set columnsToCheck = new HashSet(); Set rowsToCheck = new HashSet(); int columnStars = 0; @@ -55,9 +55,9 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem rowsToCheck.add(firstRow); while (!columnsToCheck.isEmpty() || !rowsToCheck.isEmpty()) { - for (int r: rowsToCheck) { + for (int r : rowsToCheck) { rowStars += board.rowStars(r); - for (PuzzleElement c: board.getRow(r)) { + for (PuzzleElement c : board.getRow(r)) { int column = ((StarBattleCell) c).getLocation().x; if (columns.add(column)) { columnsToCheck.add(column); @@ -65,9 +65,9 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } rowsToCheck.remove(r); } - for (int c: columnsToCheck) { + for (int c : columnsToCheck) { columnStars += board.columnStars(c); - for (PuzzleElement r: board.getCol(c)) { + for (PuzzleElement r : board.getCol(c)) { int row = ((StarBattleCell) r).getLocation().y; if (rows.add(row)) { rowsToCheck.add(row); @@ -77,14 +77,16 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } } // are the columns and regions missing an equal amount of stars - if (board.getPuzzleNumber() * columns.size() - columnStars != board.getPuzzleNumber() * rows.size() - rowStars) { + if (board.getPuzzleNumber() * columns.size() - columnStars + != board.getPuzzleNumber() * rows.size() - rowStars) { return "The number of missing stars in the columns and rows must be equal and every extraneous cell must be black!"; } return null; } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/FinishWithStarsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/FinishWithStarsDirectRule.java index 36e691e74..80ae9a4c8 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/FinishWithStarsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/FinishWithStarsDirectRule.java @@ -13,20 +13,21 @@ public class FinishWithStarsDirectRule extends DirectRule { public FinishWithStarsDirectRule() { - super("STBL-BASC-0004", + super( + "STBL-BASC-0004", "Finish With Stars", "Unknown spaces must be stars if there are just enough in a row, column, or region to satisfy the puzzle number.", "edu/rpi/legup/images/starbattle/rules/FinishWithStarDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { @@ -50,7 +51,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinColumnsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinColumnsDirectRule.java index 16951fb2a..7022a06ac 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinColumnsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinColumnsDirectRule.java @@ -8,20 +8,21 @@ public class RegionsWithinColumnsDirectRule extends DirectRule { public RegionsWithinColumnsDirectRule() { - super("STBL-BASC-0005", + super( + "STBL-BASC-0005", "Regions Within Columns", "If a number of regions is fully contained by a number of columns with an equal number of missing stars, spaces of other regions in those columns must be black.", "edu/rpi/legup/images/starbattle/rules/RegionsWithinColumnsDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { @@ -30,7 +31,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinRowsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinRowsDirectRule.java index 27dc001a0..7ab50d42b 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinRowsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RegionsWithinRowsDirectRule.java @@ -8,20 +8,21 @@ public class RegionsWithinRowsDirectRule extends DirectRule { public RegionsWithinRowsDirectRule() { - super("STBL-BASC-0006", + super( + "STBL-BASC-0006", "Regions Within Rows", "If a number of regions is fully contained by a number of rows with an equal number of missing stars, spaces of other regions in those rows must be black.", "edu/rpi/legup/images/starbattle/rules/RegionsWithinRowsDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { @@ -31,7 +32,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinColumnsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinColumnsDirectRule.java index 4054ec017..2df20e464 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinColumnsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinColumnsDirectRule.java @@ -5,30 +5,25 @@ 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.starbattle.StarBattleBoard; -import edu.rpi.legup.puzzle.starbattle.StarBattleCell; -import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; - -import java.util.HashSet; -import java.util.Set; public class RowsWithinColumnsDirectRule extends DirectRule { public RowsWithinColumnsDirectRule() { - super("STBL-BASC-0007", + super( + "STBL-BASC-0007", "Rows Withing Columns", "If a number of rows is fully contained by a number of columns with an equal number of missing stars, spaces of other rows in those columns must be black.", "edu/rpi/legup/images/starbattle/rules/RowsWithinColumnsDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { @@ -38,7 +33,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinRegionsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinRegionsDirectRule.java index 7af2c79ed..78f8f00e7 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinRegionsDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/RowsWithinRegionsDirectRule.java @@ -8,42 +8,42 @@ import edu.rpi.legup.puzzle.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; - import java.util.HashSet; import java.util.Set; public class RowsWithinRegionsDirectRule extends DirectRule { public RowsWithinRegionsDirectRule() { - super("STBL-BASC-0008", + super( + "STBL-BASC-0008", "Rows Within Regions", "If a number of rows is fully contained by a number of regions with an equal number of missing stars, spaces of other rows in those regions must be black.", "edu/rpi/legup/images/starbattle/rules/RowsWithinRegionsDirectRule.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { - //assumption: the rule has been applied to its fullest extent and the rows and regions - //are now mutually encompassing + // assumption: the rule has been applied to its fullest extent and the rows and regions + // are now mutually encompassing StarBattleBoard board = (StarBattleBoard) transition.getBoard(); StarBattleCell cell = (StarBattleCell) board.getPuzzleElement(puzzleElement); if (cell.getType() != StarBattleCellType.BLACK) { return "Only black cells are allowed for this rule!"; } - //the rows that are contained + // the rows that are contained Set rows = new HashSet(); - //the regions that contain them + // the regions that contain them Set regions = new HashSet(); - //rows and regions to process + // rows and regions to process Set rowsToCheck = new HashSet(); Set regionsToCheck = new HashSet(); int rowStars = 0; @@ -52,9 +52,9 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem regionsToCheck.add(cell.getGroupIndex()); while (!rowsToCheck.isEmpty() || !regionsToCheck.isEmpty()) { - for (int r: regionsToCheck) { + for (int r : regionsToCheck) { regionStars += board.getRegion(r).numStars(); - for (PuzzleElement ro: board.getRegion(r).getCells()) { + for (PuzzleElement ro : board.getRegion(r).getCells()) { int row = ((StarBattleCell) ro).getLocation().y; if (rows.add(row)) { rowsToCheck.add(row); @@ -62,10 +62,10 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } regionsToCheck.remove(r); } - for (int r: rowsToCheck) { + for (int r : rowsToCheck) { rowStars += board.rowStars(r); for (int i = 0; i < board.getSize(); ++i) { - int region = board.getCell(i,r).getGroupIndex(); + int region = board.getCell(i, r).getGroupIndex(); if (regions.add(region)) { regionsToCheck.add(region); } @@ -74,14 +74,16 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } } // are the columns and regions missing an equal amount of stars - if (board.getPuzzleNumber() * rows.size() - rowStars != board.getPuzzleNumber() * regions.size() - regionStars) { + if (board.getPuzzleNumber() * rows.size() - rowStars + != board.getPuzzleNumber() * regions.size() - regionStars) { return "The number of missing stars in the rows and regions must be equal and every extraneous cell must be black!"; } return null; } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java index 0aa147c6f..df900dcd5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java @@ -1,31 +1,29 @@ package edu.rpi.legup.puzzle.starbattle.rules; -import edu.rpi.legup.model.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.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; - import java.util.ArrayList; import java.util.List; public class StarOrEmptyCaseRule extends CaseRule { public StarOrEmptyCaseRule() { - super("STBL-CASE-0002", + super( + "STBL-CASE-0002", "Star or Empty", "Each unknown space is either a star or empty.", "edu/rpi/legup/images/starbattle/cases/StarOrEmptyCaseRule.png"); } /** - * Checks whether the {@link TreeTransition} logically follows from the parent node using this rule. This method is - * the one that should overridden in child classes. + * Checks whether the {@link TreeTransition} logically follows from the parent node using this + * rule. This method is the one that should overridden in child classes. * * @param transition transition to check * @return null if the child node logically follow from the parent node, otherwise error message @@ -39,20 +37,25 @@ public String checkRuleRaw(TreeTransition transition) { TreeTransition case1 = childTransitions.get(0); TreeTransition case2 = childTransitions.get(1); - if (case1.getBoard().getModifiedData().size() != 1 || - case2.getBoard().getModifiedData().size() != 1) { - return super.getInvalidUseOfRuleMessage() + ": This case rule must have 1 modified cell for each case."; + if (case1.getBoard().getModifiedData().size() != 1 + || case2.getBoard().getModifiedData().size() != 1) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must have 1 modified cell for each case."; } StarBattleCell mod1 = (StarBattleCell) case1.getBoard().getModifiedData().iterator().next(); StarBattleCell mod2 = (StarBattleCell) case2.getBoard().getModifiedData().iterator().next(); if (!mod1.getLocation().equals(mod2.getLocation())) { - return super.getInvalidUseOfRuleMessage() + ": This case rule must modify the same cell for each case."; + return super.getInvalidUseOfRuleMessage() + + ": This case rule must modify the same cell for each case."; } - if (!((mod1.getType() == StarBattleCellType.STAR && mod2.getType() == StarBattleCellType.BLACK) || - (mod2.getType() == StarBattleCellType.STAR && mod1.getType() == StarBattleCellType.BLACK))) { - return super.getInvalidUseOfRuleMessage() + ": This case rule must create a star cell and a black cell."; + if (!((mod1.getType() == StarBattleCellType.STAR + && mod2.getType() == StarBattleCellType.BLACK) + || (mod2.getType() == StarBattleCellType.STAR + && mod1.getType() == StarBattleCellType.BLACK))) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must create a star cell and a black cell."; } return null; @@ -74,7 +77,7 @@ public CaseBoard getCaseBoard(Board board) { /** * Gets the possible cases at a specific location based on this case rule * - * @param board the current board state + * @param board the current board state * @param puzzleElement equivalent puzzleElement * @return a list of elements the specified could be */ diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/SurroundStarDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/SurroundStarDirectRule.java index e1c6f3084..89857875d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/SurroundStarDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/SurroundStarDirectRule.java @@ -13,20 +13,21 @@ public class SurroundStarDirectRule extends DirectRule { public SurroundStarDirectRule() { - super("STBL-BASC-0009", + super( + "STBL-BASC-0009", "Surround Star", "Any space adjacent to a star must be black.", "edu/rpi/legup/images/starbattle/rules/SurroundStar.png"); } /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule + * 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 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 + * @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) { @@ -49,7 +50,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem } /** - * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}. + * 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 @@ -60,4 +62,3 @@ public Board getDefaultBoard(TreeNode node) { return null; } } - diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooFewStarsContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooFewStarsContradictionRule.java index d1ed62107..e88b7c6b9 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooFewStarsContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooFewStarsContradictionRule.java @@ -3,31 +3,30 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; 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.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; import edu.rpi.legup.puzzle.starbattle.StarBattleRegion; - import java.awt.*; public class TooFewStarsContradictionRule extends ContradictionRule { public TooFewStarsContradictionRule() { - super("STBL-CONT-0002", + super( + "STBL-CONT-0002", "Too Few Stars", "There are too few stars in this region/row/column and there are not enough places to put the remaining stars.", "edu/rpi/legup/images/starbattle/contradictions/TooFewStarsContradictionRule.png"); } /** - * Checks whether the transition has a contradiction at the specific puzzleElement index using this rule + * Checks whether the transition has a contradiction at the specific puzzleElement index using + * this rule * - * @param board board to check contradiction + * @param board board to check contradiction * @param puzzleElement equivalent puzzleElement * @return null if the transition contains a contradiction at the specified puzzleElement, - * otherwise error message + * otherwise error message */ @Override public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { @@ -51,7 +50,7 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { } StarBattleRegion region = sbBoard.getRegion(cell); int regionCount = 0; - for (StarBattleCell c: region.getCells()) { + for (StarBattleCell c : region.getCells()) { if (c.getType() != StarBattleCellType.BLACK) { ++regionCount; } @@ -61,4 +60,4 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { } return super.getNoContradictionMessage(); } -} \ No newline at end of file +} diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooManyStarsContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooManyStarsContradictionRule.java index 2ae424d45..12603a6ba 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooManyStarsContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/TooManyStarsContradictionRule.java @@ -3,34 +3,33 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; 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.lightup.LightUpCell; import edu.rpi.legup.puzzle.starbattle.StarBattleBoard; import edu.rpi.legup.puzzle.starbattle.StarBattleCell; import edu.rpi.legup.puzzle.starbattle.StarBattleCellType; import edu.rpi.legup.puzzle.starbattle.StarBattleRegion; - import java.awt.*; import java.util.List; public class TooManyStarsContradictionRule extends ContradictionRule { - private final String INVALID_USE_MESSAGE = "Contradiction must be applied to a cell containing a star."; + private final String INVALID_USE_MESSAGE = + "Contradiction must be applied to a cell containing a star."; public TooManyStarsContradictionRule() { - super("STBL-CONT-0001", + super( + "STBL-CONT-0001", "Too Many Stars", "There are too many stars in this region/row/column.", "edu/rpi/legup/images/starbattle/contradictions/TooManyStarsContradictionRule.png"); } /** - * Checks whether the transition has a contradiction at the specific puzzleElement index using this rule + * Checks whether the transition has a contradiction at the specific puzzleElement index using + * this rule * - * @param board board to check contradiction + * @param board board to check contradiction * @param puzzleElement equivalent puzzleElement * @return null if the transition contains a contradiction at the specified puzzleElement, - * otherwise error message + * otherwise error message */ @Override public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { @@ -111,4 +110,4 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { } return null; } -} \ No newline at end of file +} diff --git a/src/main/java/edu/rpi/legup/utility/LegupUtils.java b/src/main/java/edu/rpi/legup/utility/LegupUtils.java index 770ccc6a2..ce21a8d9a 100644 --- a/src/main/java/edu/rpi/legup/utility/LegupUtils.java +++ b/src/main/java/edu/rpi/legup/utility/LegupUtils.java @@ -98,8 +98,7 @@ private static List findClassesZip(String path, String packageName) try { Class c = Class.forName(substr); classes.add(c); - } - catch (LinkageError | ClassNotFoundException e) { + } catch (LinkageError | ClassNotFoundException e) { System.out.println("Failed on " + substr); } } diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png new file mode 100644 index 0000000000000000000000000000000000000000..a74654d4301f75defc639727604f3d59f05612a3 GIT binary patch literal 2835 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 W-$D%jr3*N)f}HK$?8r8Oq<;bxYC}%| literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png new file mode 100644 index 0000000000000000000000000000000000000000..214aa53483ccc0f6749bffda004ccfc2f70ded29 GIT binary patch literal 3455 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/OneOrZeroCaseRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/OneOrZeroCaseRule.png new file mode 100644 index 0000000000000000000000000000000000000000..73072f2ce5ea9d189fe55058aa6a4fa09ecc3979 GIT binary patch literal 5578 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/OneTileGapDirectRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/OneTileGapDirectRule.png new file mode 100644 index 0000000000000000000000000000000000000000..b68f67e441d3519f17daffd48da37f35e9b3bcfb GIT binary patch literal 2751 zcmai$3sh3s8pp{CWlla)Oe`nS#-N;3%6vr{iYaM?_=-%^AvA^|Qy`ycLq%pzn$J{9 zqa5@73MNIgNqb>Lr6Xym>15ne!)HX6-s3cD&Aqc`=AL!V*=K)yuk-D-zu))&_E`en zOIK&D4hRI&#d%|iKq~>Bd)mu^_x|~Z$AJdSaK{B`16Q*4;WVIc%JkgN^pB2Y#zn+Z zKv74d>69%Dax8^%lyM}QsrpyDD==xx(j<>qN(7S{eH0!*rBgrwED9Xu0LL7Qg>SXn zY7e)wciDz=0W5^Qa8GQ&6CG>{2&4nUVKD*myorH`Y<}ySGgH6Ti1fp)bgeH`pQ<+u zx8mlt##jyNvt#PLrY414aLG_WFlk$m^mUdS7I%L*w)r6V7Ju=(P*9c@M+<2H-8I~< zUU=$^pg-rx@5S}ZI&|2j2^?Pc zkG16gNEO;d87p}(a&|5I!8e4)uXE6{LnME@P4df1XMq=2f98Z1W*Jmlr*szq1o`al z`%;h&7(##}|7VE*QfxxbfO=X42I2w(N5n%d)dT0s23DqX82EI)fs)6=BdA5YTh&D9 z=~;F=D?w!JFEYwS0EWQ4v^29!uLm<9Bfrl?ajm=7p}$pAfAIVFaRhST!vd@r z53u#a$SHR&)P?!5$ zF&T6mA?#F@v~6`RB=hpxc-hA`os=jkE=r2}pv!4=&+y>vlr)ZSQGEh>;nG0Mp27*E z>Sq3_wbO>V5T6yp%3n^Gw&F?oZ$Ngl>9=I%#j*}m>R#_KS`o-O!TzPLhDYX1ciJ-o zUrsF>Yq2?qG3Qf@Xd;;^N~-EV^IaTg8XGE?*RSe0rrTvtRWV(rewkeNG9iVo*1Wt| zF(9h_BGC$g)amUXGp()M>};k-lna3E<%UKduF0z%dn-%|m1Afmg*ha(hxO&h7vTve z)mbL0ke9f^58AC}I4_NILiIhcgH>+J^xCLQSC1N;Fg*C}+ zb_3l#y!*!;mOst=J#vh>)V?AUvT~1{MU>C6{9&yn>V?Q7+oRQ*u{Kq6C33RHBs&S# zxkg)puX+7(Mv9Fw$MjWf@7Tl*ldaCZG_rZ>0GLvK6G-W$i~%O~#kz1OD#%_0I4PeV z>OKqDq^dTzj=e9Gz$a=pu||6Gwxf;ef>I+@v?T119a7Daey&@CMuIo+sCVn{|60ln zH4$FNLUbi!s&Vz%_>#u2>mp3K!;v{w7gSkx<4;M7cf*0zf>_s*J4uW3?@jOdWuSaJ zQjKU6+mYRpyDhb&@o2+rV-5uJyke{<=dmq)A!5Dvvj3aX^-l6CdWb34B4CRxs>GuB z+X?m%LOpwTXU|e#2j>sVGYRt!#NR{%aF1T^@yoQ~Kk16k@xmh#L3u0MakRf+GGhIo z<>OBr{tkzM{eOjjKP`usJ)jmtJue)d*i@u8B|qFavHol1BWC~x9wXM}(lzQ@V96DF zj*!DuC+Dbu&B?6O84)T6*pR0{6Gd5Y%+#PyV4&r66r&i}%jbHX>(`Jo%=A`h89tV| zZksEpkezZ}gW+tYAKVZtI`kshq@s z5frU2DSG6#c;2jpwzs5ks358QI!CKIk3z~?R8C+>j67}D@m-4E*+K$hT(kbP4U!ypTM!1ET4rEih-i+L>~e#U4!_tX-(6qUJZ> zpAg^FgwAIzt^ZZXGC+lz`ZCkLLJdz2-bmjcg;rrm`SSXQ2seDO$M(HOOlafHi4JQL z%}T~F>o3a5pLqDJOLa}#{ZS=_yw5cDJp6;k@V})|ITlA8<{6QFp9*YAtM=qmp4eVb z{A#p+23`K{J~%X!GsknHma!M^>e@f`-Za`v0b>Z3juIqZ(MwU}`QQl#Ce}gc4ev$S z*oJMc5ZY`&avh!{~R zr`uFz^yk-H3K{sy%51c(ZvHHce2pHWQI@1;UwpmJL&Wg(tM8QzA2T5P5-pa%Wy>BE z3HMw~!D7?-X&=-Ly?gwiem8bt5^lpbBwY4tn7egg=7;mIg3oIr`Q4HDhQj`x`C^8) z#0W?M;2zg;P>S1E{@nU*NzxqMLWYb&L`G2TqMbH}^Ao9Cqbxo<;>v0Cr*ZvJdg5<9 z2*=Z_I%%t+$2|Su$Q_=_)GbScZ{0d$>ntO|kZej{uN5}4biC)|+xcxMMS0qnONw}@ zv|kBis{VccD)Jf+zeyREH_BUsvx10vSS_8|G3z#~DG^WJxBo%8ZlVpm@si?gf$O8gXF zxK8-V48wcVgZmU67fP`gbg(yIxgU806m1BT8`ikb)R_`8dkfoxm?xT+|l| zV7U>n?4)t2eHS2WD(S@^1_Gib0^1hF6V`wy_WiK(YD!D3$mC4dXl%2YO+lCE+sQ#h uTqJ0rCdzuJ`EtlDbHy?6@29KNi_1(v%rOsAUJ`J)1mQgK*jo2+&VK+~O8lz; literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png new file mode 100644 index 0000000000000000000000000000000000000000..67a4e47f363222af68afe45acacd0783f0f35319 GIT binary patch literal 2982 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png new file mode 100644 index 0000000000000000000000000000000000000000..862408b63a9c6d72d815b79064ea587657bc5e5e GIT binary patch literal 2508 zcma)83p|@y7Ee`YLd#NAwMww9R6QD{q}w7D)x;~}Q4+LDWE9aRD2<}VdY5`@Cdjr$ zsd(1An4yAr^?auDb%+7wl`+eu$bI-ZId(Ziw|NW9M_SQ1e zhonIukPPY~5(`K+@b-Ye0={nIfiOTwQqH5C!N3y<_DuxFDj`;GAx^=5Ave9r1Q3xF z97NEg_>c(%66KrVkmcPSW`L32j*%sq;2q*0OoBN32N6Kdp#%u*Gz4*-3^6=uXaqTF zbjHvWXb_AY#0u$rWbU932qbkBg+w@q(*=_V@=TKwOIYe$UWan6V+SG&kZ({(I`Rby zS%`dL_q|fY>b!I3C71W4_u`ar}h@v4pK0QUV^9La|f%4u<^=c~2Ow|#Iq?KfBMVYT^ zjWv5!y=n-0S%27P_PXgKePXWhh#A2UD&F#3mz$+>`l2l_da}RnP)}bGyfofo%ViJTUOuytPATheT2gm8x^1TBlve|e#U@S_ zWJUXthgY>ErAGbW?AuC!E||;w)So{>NKEWi=auSv-#B|+QV}f8u)u)!0H={tw7A0n zNlWg*K%g<5(+GdAYeoGuU17N`PNL|2yxen~jbN{hyZ9b23>T^-WM zbURm&+-$2T4=);SjlrzWyK`t+OC3hW&#zMCC5zWr7y~NCXneJ7mDUpmsCjdR5!i@d9j4j3 zs_f$7Ba!@hwWEOY8!ooIToc+ms#$dF?j;lTbm$CchNpH#H^ISLSt^-gpBBw@ua z<(X54*XF`qvJmfDDx2yX;>~I^0}P7mZU(;npx3;H63Q-kD9X#G<(;8ZMALFUsW-?- ze_BaXj$o!;*X0JFb`6WM=PwPY20e|KsGj@sB^dV zzrjiZvFrB`CxM8N?|Q%)f(v=Xnw-wz>d|9m1&oS`YHCdV+G)Y}xbJ?76RYs3HKT05 zI#k1^nbVz1x^a+EoRHVyex&^ujAaV!iC-Y*K0xzDy4N%W1#6FmzaIMnuvYWrde=%7 zy_DyPwOEZfZknHFaO3#FbV%uIRNL@;CJV3hKCE>%FDVszF=~Hq45MO%zO*T9r@`6Y zPqm;YjEUJ-kP&H&3TOWS+8iJiwb%=q&=cK#+s$A$da!wyU*7z}PEU%x?)~TYUtHj0 zs%BAxM-c91aBXwMj(0X}-VUTTIdRFQ`&_aF!o9}&2|K-LJg<5sQnu)ge6|v0s83iW zm|+F!SYE1xU7%Brqn-9@M1s-D4b<3LvZY(Rlt-v%ipVRi=b?vw-pJfJqk-OvrOhr; ze3b#*D(19U`3;?VYLDqc%s!UFAlU-r1vU|wr`s6(Q8u#lbUisrjXw>(aL17aa9#8{ z&I>-CEXbNZGSm#!R8=(yHC=e$t-(4tGn@FzXt1K018@2lrzPiOj2r$pAO_F=Cgc1H z8XEqXiu&W*5f(v0M)-0!?!q$d@0yce5^OaTv-^OQbe6-?DN_%tck7{__jJYlYTaK*ZfEMipV;Cys58|Gl%#h^@%$aE-m7yH4NQ+JPAkQ6 zvE_h|Z3frqO{nhv>=J+Qu4LB#wR_vOTb@;%;>C3%%NasneS%yv{$2DsHP1u*C_I6p zpA7!G#|DTd^+qC$WeR^_Wal)2`+-Ll@{~PWVHZ+iW&QUFGW8Dk_o2%u$Y&xe4k#?_yKc7UweQ3_)RWjD(}SUUa{2X#QFp@fT z*x%8;JS?^rOR;D0HN28?fgM&TYH#lpt1%JT$ILSA8JA+CReX5#>*=I>Ps-W)Q23}l z#x-!l*7S4~L-dx2?PrF?K2SWr{$VJ0rYGNLsF|Dmc}DgvAO6>!l9bY+4#98YmCO^y z@AKE=L|!eGt%s!pn5wb~6~ujo!$kRwZ90u#54)hBXTyF~NFG8>iQGr*F@=xI%bT{$ zc!v{?#z7W7!dr>j>9bfML=UnR&{`Zv2dz-S#KV7H#lM&3{6O!%pf>Hhf0JpQ9jACH ztY`3-J%6)KkFgHU70AVgFS{dU3<%{mpGX+cv+n;uGC!IZ*`n}x&#E=>rv*Y;*&{2@ HUy1z(|GtR) literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png new file mode 100644 index 0000000000000000000000000000000000000000..029bd12ac8782f97428d092ee56187d0aa7d77cf GIT binary patch literal 2793 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config index 4aef6de60..07b0b0586 100644 --- a/src/main/resources/edu/rpi/legup/legup/config +++ b/src/main/resources/edu/rpi/legup/legup/config @@ -4,6 +4,10 @@ qualifiedClassName="edu.rpi.legup.puzzle.battleship.Battleship" fileType=".xml" fileCreationDisabled="true"/> +