Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tree Tent Test Suite #775

Merged
merged 35 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
34564fb
TentForTree test cases
jadeandtea Mar 12, 2024
f3ffcae
Incomplete test for already connected tree
jadeandtea Mar 15, 2024
7c46073
Test for Fill in Row Case Rule
jadeandtea Mar 15, 2024
8af24e9
Fill in Row Test Cases
jadeandtea Mar 15, 2024
904656e
Fill in Row Test Cases
jadeandtea Mar 15, 2024
024798f
Comments
jadeandtea Mar 19, 2024
c89190d
Merge branch 'Bram-Hub:master' into TreeTent-Test-Suite
jadeandtea Mar 19, 2024
bbcb5f7
Fix TreeTent Puzzle Editor
jadeandtea Mar 19, 2024
ecd3a7c
LinkTentCaseRule Four Trees Test Case
jadeandtea Mar 19, 2024
1c32397
LinkTentCaseRule Various Test Cases
jadeandtea Mar 19, 2024
2a7c31a
TreeTent Puzzle Editor Fix
jadeandtea Mar 19, 2024
89bb382
LinkTreeCaseRule Test Cases
jadeandtea Mar 21, 2024
aa31c31
Reset puzzle
jadeandtea Mar 22, 2024
46df351
Improved FillInRowCaseRule
jadeandtea Mar 24, 2024
dc6e3e0
Fix FillInRowCaseRule
jadeandtea Mar 24, 2024
d0ea2a1
Implement Copy Clue function
jadeandtea Mar 26, 2024
6f84ee5
Allow Importing Puzzle-Specific Puzzle Elements
jadeandtea Mar 26, 2024
0362f80
Fix Puzzles Uneven Sides
jadeandtea Mar 26, 2024
49e8fc4
Check Rule on Columns
jadeandtea Mar 29, 2024
9a23697
Change test puzzle names
jadeandtea Mar 29, 2024
5582367
FillInRowCaseRule Test
jadeandtea Mar 29, 2024
69a011f
TreeForTent tests and TentForTree tests
jadeandtea Apr 2, 2024
1a54ab1
Minor formatting changes
jadeandtea Apr 5, 2024
5819bf8
Fix boards with uneven side lengths
jadeandtea Apr 9, 2024
806f9a0
Comments
jadeandtea Apr 9, 2024
30bc764
Standardizing Comments
jadeandtea Apr 9, 2024
06eb109
Standardizing Comments
jadeandtea Apr 16, 2024
a098868
Merge branch 'dev' into TreeTent-Test-Suite
jadeandtea Apr 16, 2024
4d97969
Fix Build Issues
jadeandtea Apr 16, 2024
7c69e2a
Merge branch 'TreeTent-Test-Suite' of https://github.com/jadeandtea/L…
jadeandtea Apr 16, 2024
2f3f069
Comment out problematic file
jadeandtea Apr 16, 2024
46cbae6
Uncommenting problematic test
jadeandtea Apr 16, 2024
c20aff0
Update file name
jadeandtea Apr 16, 2024
8a28e74
Merge branch 'dev' into TreeTent-Test-Suite
charlestian23 Apr 19, 2024
c6f64ab
Commented out Star Battle test
charlestian23 May 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions puzzles files/treetent/8x8 TreeTent Easy/1646651
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Legup version="2.0.0">
<Legup version="3.0.0">
<saved/>
<puzzle name="TreeTent">
<board height="8" width="8">
<cells>
Expand Down Expand Up @@ -38,5 +39,5 @@
</axis>
</board>
</puzzle>
<solved isSolved="false" lastSaved="--"/>
<solved isSolved="false" lastSaved="2024-03-12 17:29:25"/>
</Legup>
18 changes: 17 additions & 1 deletion src/main/java/edu/rpi/legup/model/PuzzleImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
* <p> 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<String> getImporterElements() {
List<String> elements = new ArrayList<>();
elements.add("cell");
return elements;
}

/**
* Creates the proof for building
*
Expand Down Expand Up @@ -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<String> elements = getImporterElements();
if (elements.contains(node.getNodeName().toLowerCase())) {
Board board = transition.getBoard();
PuzzleElement cell = puzzle.getFactory().importCell(node, board);

Expand Down
46 changes: 28 additions & 18 deletions src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -168,20 +178,20 @@ public List<TreeTentCell> 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<TreeTentCell> getRowCol(int index, TreeTentType type, boolean isRow) {
List<TreeTentCell> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ public void setType(TreeTentType type) {
}

public TreeTentClue copy() {
return null;
return new TreeTentClue(data, clueIndex, type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
}

Expand Down Expand Up @@ -105,6 +107,8 @@ public void mouseReleased(MouseEvent e) {
}
dragStart = null;
lastCellPressed = null;
} else {
super.mouseReleased(e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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<String> getImporterElements() {
List<String> elements = new ArrayList<>();
elements.add("cell");
elements.add("line");
return elements;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
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;
import edu.rpi.legup.puzzle.treetent.TreeTentClue;
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 {

Expand Down Expand Up @@ -61,7 +65,7 @@ public CaseBoard getCaseBoard(Board board) {
*/
@Override
public ArrayList<Board> getCases(Board board, PuzzleElement puzzleElement) {
ArrayList<Board> cases = new ArrayList<Board>();
ArrayList<Board> cases;
List<TreeTentCell> group;
int tentsLeft;
TreeTentClue clue = ((TreeTentClue) puzzleElement);
Expand All @@ -70,7 +74,7 @@ public ArrayList<Board> 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 {
Expand All @@ -83,60 +87,100 @@ public ArrayList<Board> 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<Board> genCombinations(
TreeTentBoard iBoard,
List<TreeTentCell> tiles,
int target,
Integer index,
boolean isRow) {
return genCombRecursive(
iBoard, tiles, tiles, target, 0, new ArrayList<TreeTentCell>(), index, isRow);
ArrayList<Board> generatedBoards = new ArrayList<>();
genCombRecursive(
iBoard, tiles, target, 0, new ArrayList<TreeTentCell>(), 0, index, generatedBoards, isRow);
return generatedBoards;
}

private ArrayList<Board> 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<TreeTentCell> original,
List<TreeTentCell> tiles,
int target,
int current,
List<TreeTentCell> selected,
int currentTile,
Integer index,
ArrayList<Board> generatedBoards,
boolean isRow) {
ArrayList<Board> 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<TreeTentCell> sub = tiles.subList(i + 1, tiles.size());
List<TreeTentCell> next = new ArrayList<TreeTentCell>(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
Expand All @@ -153,7 +197,7 @@ private boolean goodBoard(TreeTentBoard board, Integer index, boolean isRow) {
for (TreeTentCell t : tents) {
List<TreeTentCell> adj = board.getAdjacent(t, TreeTentType.TENT);
List<TreeTentCell> diag = board.getDiagonals(t, TreeTentType.TENT);
if (adj.size() > 0 || diag.size() > 0) {
if (!adj.isEmpty() || !diag.isEmpty()) {
return false;
}
}
Expand Down
Loading
Loading