Skip to content

Commit

Permalink
Bugfix 549 (#682)
Browse files Browse the repository at this point in the history
* Simplify rule names

* Contradiction Test Suite

* checkstyle

* revert changes to dev

* null transitions and propagation bugfixes

* 2 char/hour

* cleanup

* Case rule dependency locking

* cleanup

* chellstyle

* cleanup

* move selection to transition

* modified data check

* cleanup

* Skyscrapers gneralization

* cleanup

* cleanup

* review changes

---------

Co-authored-by: Charles Tian <[email protected]>
  • Loading branch information
ThisMatt and charlestian23 authored Jan 24, 2024
1 parent f37f221 commit 5048ee6
Show file tree
Hide file tree
Showing 18 changed files with 1,354 additions and 994 deletions.
31 changes: 0 additions & 31 deletions puzzles files/skyscrapers/1646651

This file was deleted.

47 changes: 0 additions & 47 deletions puzzles files/skyscrapers/easy1.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public void executeCommand() {
board.setModifiable(false);
transition.setBoard(board);
transition.setRule(caseRule);
transition.setSelection(elementView.getPuzzleElement().copy());
caseTrans.add(transition);

TreeNode childNode = (TreeNode) tree.addTreeElement(transition);
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public abstract class PuzzleElement<T> {
protected boolean isModified;
protected boolean isGiven;
protected boolean isValid;
protected int casesDepended;

/**
* PuzzleElement Constructor creates a new puzzle element.
Expand All @@ -22,6 +23,7 @@ public PuzzleElement() {
this.isModified = false;
this.isGiven = false;
this.isValid = true;
this.casesDepended = 0;
}

/**
Expand Down Expand Up @@ -148,6 +150,24 @@ public void setValid(boolean isValid) {
this.isValid = isValid;
}

/**
* Get the number of case rules that depend upon the state of this element
*
* @return number of cases
*/
public int getCasesDepended() {
return this.casesDepended;
}

/**
* Sets the number of case rules that depend upon the state of this element
*
* @param cases number of cases
*/
public void setCasesDepended(int cases) {
this.casesDepended = cases;
}

/**
* Tests whether two puzzle elements objects have the same puzzle element
*
Expand Down
29 changes: 27 additions & 2 deletions src/main/java/edu/rpi/legup/model/rules/CaseRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
import edu.rpi.legup.model.tree.TreeTransition;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static edu.rpi.legup.model.rules.RuleType.CASE;

Expand Down Expand Up @@ -79,6 +78,7 @@ public String checkRule(TreeTransition transition) {

String check = checkRuleRaw(transition);

// Mark transition and new data as valid or not
boolean isCorrect = (check == null);
for (TreeTransition childTrans : parentNodes.get(0).getChildren()) {
childTrans.setCorrect(isCorrect);
Expand Down Expand Up @@ -125,6 +125,31 @@ public String checkRuleAt(TreeTransition transition, PuzzleElement puzzleElement
*/
@Override
public abstract String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement);

/**
* Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid
* Overridden by case rules dependent on more than just the modified data
*
* @param board board state at application
* @param puzzleElement selected puzzleElement
* @return List of puzzle elements (typically cells) this application of the case rule depends upon.
* Defaults to any element modified by any case
*/
public List<PuzzleElement> dependentElements(Board board, PuzzleElement puzzleElement) {
List<PuzzleElement> elements = new ArrayList<>();

List<Board> cases = getCases(board,puzzleElement);
for (Board caseBoard : cases) {
Set<PuzzleElement> data = caseBoard.getModifiedData();
for (PuzzleElement element : data) {
if(!elements.contains(board.getPuzzleElement(element))){
elements.add(board.getPuzzleElement(element));
}
}
}

return elements;
}
}


4 changes: 4 additions & 0 deletions src/main/java/edu/rpi/legup/model/rules/DirectRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public String checkRule(TreeTransition transition) {
transition.getParents().get(0).getChildren().size() != 1) {
return "State must have only 1 parent and 1 child";
}
else if (finalBoard.getModifiedData().isEmpty()) {
// null transition
return null;
}
else {
return checkRuleRaw(transition);
}
Expand Down
64 changes: 59 additions & 5 deletions src/main/java/edu/rpi/legup/model/tree/TreeTransition.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import edu.rpi.legup.model.gameboard.Board;
import edu.rpi.legup.model.gameboard.PuzzleElement;
import edu.rpi.legup.model.rules.CaseRule;
import edu.rpi.legup.model.rules.Rule;
import edu.rpi.legup.model.rules.RuleType;

Expand All @@ -12,6 +13,8 @@ public class TreeTransition extends TreeElement {
private ArrayList<TreeNode> parents;
private TreeNode childNode;
private Rule rule;

private PuzzleElement selection;
private boolean isCorrect;
private boolean isVerified;

Expand All @@ -26,6 +29,7 @@ public TreeTransition(Board board) {
this.childNode = null;
this.board = board;
this.rule = null;
this.selection = null;
this.isCorrect = false;
this.isVerified = false;
}
Expand Down Expand Up @@ -87,13 +91,42 @@ public void propagateChange(PuzzleElement element) {
}
}
else {
// Overwrite previous modifications to this element
board.removeModifiedData(board.getPuzzleElement(element));

// apply changes to tranistion
board.notifyChange(element);

// mark first transition as modified
if (!board.getPuzzleElement(element).equalsData(parents.get(0).getBoard().getPuzzleElement(element))) {
board.addModifiedData(element);
}

// propagate to children
if (childNode != null) {
board.notifyChange(element);
childNode.getBoard().notifyChange(element.copy());
for (TreeTransition child : childNode.getChildren()) {
PuzzleElement copy = element.copy();

// find starting board
TreeNode head = childNode;
while (head.getParent() != null) {
head = head.getParent().getParents().get(0);
}
Board headBoard = head.getBoard();

PuzzleElement copy = element.copy();
// Set as modifiable if reverted to starting value (and started modifiable)
if (headBoard.getPuzzleElement(element).equalsData(element)) {
copy.setModifiable(headBoard.getPuzzleElement(element).isModifiable());
}
else{
copy.setModifiable(false);
child.propagateChange(copy);
}

// apply changes to result node
childNode.getBoard().notifyChange(copy);

// apply to all child transitions
for (TreeTransition child : childNode.getChildren()) {
child.propagateChange(copy.copy());
}
}
}
Expand Down Expand Up @@ -327,6 +360,27 @@ public void setRule(Rule rule) {
isVerified = false;
}

/**
* Gets he selected element associated with this transition
*
* @return If this is a case rule, the selected element for that rule, null otherwise
*/
public PuzzleElement getSelection() {
if (this.rule instanceof CaseRule) {
return selection;
}
return null;
}

/**
* Sets the selected element associated with this transition
*
* @param selection selected element for this transition
*/
public void setSelection(PuzzleElement selection) {
this.selection = selection;
}

/**
* Gets whether this transition is correctly justified
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,67 @@ private List<LightUpCell> getAdjacentCells(LightUpBoard board, LightUpCell cell)
}
return cells;
}

/**
* Returns the elements necessary for the cases returned by getCases(board,puzzleElement) to be valid
* Overridden by case rules dependent on more than just the modified data
*
* @param board board state at application
* @param puzzleElement selected puzzleElement
* @return List of puzzle elements (typically cells) this application of the case rule depends upon.
* Defaults to any element modified by any case
*/
@Override
public List<PuzzleElement> dependentElements(Board board, PuzzleElement puzzleElement) {
List<PuzzleElement> elements = new ArrayList<>();

LightUpBoard puzzleBoard = (LightUpBoard) board;
LightUpCell point = (LightUpCell)puzzleBoard.getPuzzleElement(puzzleElement);

List<LightUpCell> cells = getAdjacentCells(puzzleBoard,point);

for (LightUpCell cell : cells) {
//add cells that can light adjacents from any direction
Point location = cell.getLocation();
for (int i = location.x; i < puzzleBoard.getWidth(); i++) {
System.out.println(i);
LightUpCell c = puzzleBoard.getCell(i, location.y);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else if (!elements.contains(board.getPuzzleElement(c))) {
elements.add(board.getPuzzleElement(c));
}
}
for (int i = location.x; i >= 0; i--) {
LightUpCell c = puzzleBoard.getCell(i, location.y);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else if (!elements.contains(board.getPuzzleElement(c))) {
elements.add(board.getPuzzleElement(c));
}
}
for (int i = location.y; i < puzzleBoard.getHeight(); i++) {
LightUpCell c = puzzleBoard.getCell(location.x, i);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else if (!elements.contains(board.getPuzzleElement(c))) {
elements.add(board.getPuzzleElement(c));
}
}
for (int i = location.y; i >= 0; i--) {
LightUpCell c = puzzleBoard.getCell(location.x, i);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else if (!elements.contains(board.getPuzzleElement(c))) {
elements.add(board.getPuzzleElement(c));
}
}
}

return elements;
}
}
Loading

0 comments on commit 5048ee6

Please sign in to comment.