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/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/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/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/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() { 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 000000000..a74654d43 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png differ 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 000000000..214aa5348 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png differ 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 000000000..73072f2ce Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/OneOrZeroCaseRule.png differ 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 000000000..b68f67e44 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/OneTileGapDirectRule.png differ 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 000000000..67a4e47f3 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png differ 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 000000000..862408b63 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png differ 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 000000000..029bd12ac Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png differ diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config index 160e4093e..a6e2fad7d 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"/> + 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