From fffa63ba7de3b82ffbbda44c4fee8bcc4eccdec8 Mon Sep 17 00:00:00 2001 From: Chase Grajeda <76405306+Chase-Grajeda@users.noreply.github.com> Date: Tue, 7 Nov 2023 12:25:25 -0500 Subject: [PATCH] Issue 413 operator transition (#680) * Began updating case rule evaluation algorithm Added new logic to checkRuleRaw in CaseRule_Generic Updated null definition in CaseRule_GenericStatement Updated STT case rule constants * Fixed immutable cell bug Fixed bug in CaseRule_GenericStatement where cells that had type UNKNOWN in a generated case-rule board were immutable; Continued debugging for CaseRule_Generic; Updated specs and method descriptors. * Finalized rule verification Added final rule verification to CaseRule_Generic; Removed debugging. --------- Co-authored-by: Charles Tian <46334090+charlestian23@users.noreply.github.com> --- .../ShortTruthTableOperation.java | 118 ++++---- .../rules/caserule/CaseRuleAnd.java | 46 +-- .../rules/caserule/CaseRuleAtomic.java | 1 - .../rules/caserule/CaseRuleConditional.java | 46 +-- .../rules/caserule/CaseRuleOr.java | 46 +-- .../rules/caserule/CaseRule_Generic.java | 144 +++++----- .../caserule/CaseRule_GenericStatement.java | 261 ++++++++---------- 7 files changed, 316 insertions(+), 346 deletions(-) diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java index 380afb4cd..bc713d407 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableOperation.java @@ -1,61 +1,57 @@ -package edu.rpi.legup.puzzle.shorttruthtable; - -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; - -public class ShortTruthTableOperation { - - public static final char AND = '^'; - public static final char OR = '|'; - public static final char NOT = '~'; - public static final char CONDITIONAL = '>'; - public static final char BICONDITIONAL = '-'; - - private ShortTruthTableOperation() { - } - - - public static String getLogicSymbol(char c) { - switch (c) { - case AND: - return "\u2227"; - case OR: - return "\u2228"; - case NOT: - return "\u00AC"; - case CONDITIONAL: - return "\u2192"; - case BICONDITIONAL: - return "\u2194"; - } - return "" + c; - } - - public static String getRuleName(char operation) { - switch (operation) { - case AND: - return "And"; - case OR: - return "Or"; - case NOT: - return "Not"; - case CONDITIONAL: - return "Conditional"; - case BICONDITIONAL: - return "Biconditional"; - } - return null; - } - - - public static boolean isOperation(char c) { - return c == AND || - c == OR || - c == NOT || - c == CONDITIONAL || - c == BICONDITIONAL; - } - - -} +package edu.rpi.legup.puzzle.shorttruthtable; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +public class ShortTruthTableOperation { + + public static final char AND = '^'; + public static final char OR = '|'; + public static final char NOT = '~'; + public static final char CONDITIONAL = '>'; + public static final char BICONDITIONAL = '-'; + + private ShortTruthTableOperation() { + } + + public static String getLogicSymbol(char c) { + switch (c) { + case AND: + return "\u2227"; + case OR: + return "\u2228"; + case NOT: + return "\u00AC"; + case CONDITIONAL: + return "\u2192"; + case BICONDITIONAL: + return "\u2194"; + } + return "" + c; + } + + public static String getRuleName(char operation) { + switch (operation) { + case AND: + return "And"; + case OR: + return "Or"; + case NOT: + return "Not"; + case CONDITIONAL: + return "Conditional"; + case BICONDITIONAL: + return "Biconditional"; + } + return null; + } + + public static boolean isOperation(char c) { + return c == AND || + c == OR || + c == NOT || + c == CONDITIONAL || + c == BICONDITIONAL; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java index ddc84df16..12fac9c4c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAnd.java @@ -1,23 +1,23 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - -public class CaseRuleAnd extends CaseRule_GenericStatement { - - public CaseRuleAnd() { - super("STTT-CASE-0001", ShortTruthTableOperation.AND, - "And", - trueCases, - falseCases); - } - - private static final ShortTruthTableCellType[][] trueCases = { - {T, T} - }; - private static final ShortTruthTableCellType[][] falseCases = { - {F, N}, - {N, F} - }; - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + +public class CaseRuleAnd extends CaseRule_GenericStatement { + + public CaseRuleAnd() { + super("STTT-CASE-0001", ShortTruthTableOperation.AND, + "And", + trueCases, + falseCases); + } + + private static final ShortTruthTableCellType[][] trueCases = { + {T, T} + }; + private static final ShortTruthTableCellType[][] falseCases = { + {F, U}, + {U, F} + }; + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java index 9b2ef7fea..f168499cc 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java @@ -20,7 +20,6 @@ public CaseRuleAtomic() { super("STTT-CASE-0002", "Atomic", "True or False", "Each unknown cell must either be true or false"); - System.out.println("Case Rule T/F constructor"); } // Adds all elements that can be selected for this case rule diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java index 867708729..a9fee2b4e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleConditional.java @@ -1,23 +1,23 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - -public class CaseRuleConditional extends CaseRule_GenericStatement { - - public CaseRuleConditional() { - super("STTT-CASE-0004", ShortTruthTableOperation.CONDITIONAL, - "Conditional", - trueCases, - falseCases); - } - - private static final ShortTruthTableCellType[][] trueCases = { - {N, T}, - {F, N} - }; - private static final ShortTruthTableCellType[][] falseCases = { - {T, F}, - }; - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + +public class CaseRuleConditional extends CaseRule_GenericStatement { + + public CaseRuleConditional() { + super("STTT-CASE-0004", ShortTruthTableOperation.CONDITIONAL, + "Conditional", + trueCases, + falseCases); + } + + private static final ShortTruthTableCellType[][] trueCases = { + {U, T}, + {F, U} + }; + private static final ShortTruthTableCellType[][] falseCases = { + {T, F}, + }; + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java index e0bc9774c..82f814cc8 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleOr.java @@ -1,23 +1,23 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - -public class CaseRuleOr extends CaseRule_GenericStatement { - - public CaseRuleOr() { - super("STTT-CASE-0005", ShortTruthTableOperation.OR, - "Or", - trueCases, - falseCases); - } - - private static final ShortTruthTableCellType[][] trueCases = { - {T, N}, - {N, T} - }; - private static final ShortTruthTableCellType[][] falseCases = { - {F, F}, - }; - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + +public class CaseRuleOr extends CaseRule_GenericStatement { + + public CaseRuleOr() { + super("STTT-CASE-0005", ShortTruthTableOperation.OR, + "Or", + trueCases, + falseCases); + } + + private static final ShortTruthTableCellType[][] trueCases = { + {T, U}, + {U, T} + }; + private static final ShortTruthTableCellType[][] falseCases = { + {F, F}, + }; + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java index 047ea5d33..9f3a7073f 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java @@ -1,73 +1,71 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.gameboard.CaseBoard; -import edu.rpi.legup.model.gameboard.PuzzleElement; -import edu.rpi.legup.model.rules.CaseRule; -import edu.rpi.legup.model.tree.TreeTransition; - -import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; -import edu.rpi.legup.puzzle.nurikabe.NurikabeType; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; - - -import java.util.ArrayList; -import java.util.List; - -public abstract class CaseRule_Generic extends CaseRule { - - public CaseRule_Generic(String ruleID, String ruleName, String title, String description) { - super(ruleID, title, description, "edu/rpi/legup/images/shorttruthtable/ruleimages/case/" + ruleName + ".png"); - } - - - /** - * Checks whether the transition logically follows from the parent node using this rule - * - * @param transition transition to check - * @return null if the child node logically follow from the parent node, otherwise error message - */ - @Override - public String checkRuleRaw(TreeTransition transition) { - List childTransitions = transition.getParents().get(0).getChildren(); - if (childTransitions.size() != 2) { - return "This case rule must have 2 children."; - } - - TreeTransition case1 = childTransitions.get(0); - TreeTransition case2 = childTransitions.get(1); - if (case1.getBoard().getModifiedData().size() != 1 || case2.getBoard().getModifiedData().size() != 1) { - return "This case rule must have 1 modified cell for each case."; - } - - ShortTruthTableCell mod1 = (ShortTruthTableCell) case1.getBoard().getModifiedData().iterator().next(); - ShortTruthTableCell mod2 = (ShortTruthTableCell) case2.getBoard().getModifiedData().iterator().next(); - if (!mod1.getLocation().equals(mod2.getLocation())) { - return "This case rule must modify the same cell for each case."; - } - - boolean firstPossibility = mod1.getType() == ShortTruthTableCellType.TRUE && mod2.getType() == ShortTruthTableCellType.FALSE; - boolean secondPossibility = mod1.getType() == ShortTruthTableCellType.FALSE && mod2.getType() == ShortTruthTableCellType.TRUE; - if (!firstPossibility && !secondPossibility) { - return "This case rule must an empty true or false cell."; - } - - return null; - } - - /** - * Checks whether the child node logically follows from the parent node - * at the specific puzzleElement index using this rule - * - * @param transition transition to check - * @param puzzleElement equivalent puzzleElement - * @return null if the child node logically follow from the parent node at the specified puzzleElement, - * otherwise error message - */ - @Override - public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { - return checkRuleRaw(transition); - } -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.CaseBoard; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.model.tree.TreeTransition; + +import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; +import edu.rpi.legup.puzzle.nurikabe.NurikabeType; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.JOptionPane; + +import com.google.firebase.database.core.utilities.Tree; + +public abstract class CaseRule_Generic extends CaseRule { + + public CaseRule_Generic(String ruleID, String ruleName, String title, String description) { + super(ruleID, title, description, "edu/rpi/legup/images/shorttruthtable/ruleimages/case/" + ruleName + ".png"); + } + + + /** + * Checks whether the transition logically follows from the parent node using this rule + * + * @param transition transition to check + * @return null if the child node logically follow from the parent node, otherwise error message + */ + @Override + public String checkRuleRaw(TreeTransition transition) { + // Validate that two children are generated + List childTransitions = transition.getParents().get(0).getChildren(); + if (childTransitions.size() != 2) { + return "ERROR: This case rule must have 2 children."; + } + + // Validate that the modified cells are of type UNKNOWN, TRUE, or FALSE + List cases = Arrays.asList(childTransitions.get(0), childTransitions.get(1)); + for (TreeTransition c : cases) { + ShortTruthTableCell mod1 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); + ShortTruthTableCell mod2 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); + if (!(mod1.getType() == ShortTruthTableCellType.TRUE || mod1.getType() == ShortTruthTableCellType.FALSE || mod1.getType() == ShortTruthTableCellType.UNKNOWN) && + (mod2.getType() == ShortTruthTableCellType.TRUE || mod2.getType() == ShortTruthTableCellType.FALSE || mod2.getType() == ShortTruthTableCellType.UNKNOWN)) { + return "ERROR: This case rule must be an unknown, true, or false cell."; + } + } + return null; + } + + /** + * Checks whether the child node logically follows from the parent node + * at the specific puzzleElement index using this rule + * + * @param transition transition to check + * @param puzzleElement equivalent puzzleElement + * @return null if the child node logically follow from the parent node at the specified puzzleElement, + * otherwise error message + */ + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + return checkRuleRaw(transition); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java index 375a60292..2a40bf45d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java @@ -1,142 +1,119 @@ -package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; - -import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.gameboard.CaseBoard; -import edu.rpi.legup.model.gameboard.PuzzleElement; - -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableStatement; -import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; - - -import java.util.ArrayList; - -public abstract class CaseRule_GenericStatement extends CaseRule_Generic { - - public CaseRule_GenericStatement(String ruleID, char operation, String title, - ShortTruthTableCellType[][] trueCases, - ShortTruthTableCellType[][] falseCases) { - super(ruleID, ShortTruthTableOperation.getRuleName(operation), - title + " case", - "A known " + title.toUpperCase() + " statement can have multiple forms"); - - this.operation = operation; - - this.trueCases = trueCases; - this.falseCases = falseCases; - } - - private final char operation; - - private final ShortTruthTableCellType[][] trueCases; - private final ShortTruthTableCellType[][] falseCases; - - protected static final ShortTruthTableCellType T = ShortTruthTableCellType.TRUE; - protected static final ShortTruthTableCellType F = ShortTruthTableCellType.FALSE; - protected static final ShortTruthTableCellType N = null; - - //Adds all elements that can be selected for this caserule - @Override - public CaseBoard getCaseBoard(Board board) { - //copy the board and add all elements that can be selected - ShortTruthTableBoard sttBoard = (ShortTruthTableBoard) board.copy(); - sttBoard.setModifiable(false); - CaseBoard caseBoard = new CaseBoard(sttBoard, this); - - //add all elements that can be selected for the case rule statement - for (PuzzleElement element : sttBoard.getPuzzleElements()) { - - System.out.println("GetCaseBoard Testing: " + element); - - //get the cell object - ShortTruthTableCell cell = sttBoard.getCellFromElement(element); - //the cell must match the symbol - if (cell.getSymbol() != this.operation) continue; - - System.out.println(" Selectable... checking logic"); - - //the statement must be assigned with unassigned sub-statements - if (!cell.getType().isTrueOrFalse()) continue; - System.out.println(" Operation is known"); - if (cell.getStatementReference().getRightStatement().getCell().getType().isTrueOrFalse()) continue; - System.out.println(" right side is unknown"); - if (this.operation != ShortTruthTableOperation.NOT && - cell.getStatementReference().getRightStatement().getCell().getType().isTrueOrFalse()) { - continue; - } - System.out.println(" left side is unknown"); - - System.out.println(" Valid choice"); - //if the element has passed all the checks, it can be selected - caseBoard.addPickableElement(element); - - } - return caseBoard; - } - - /** - * Gets the possible cases at a specific location based on this case rule - * - * @param board the current board state - * @param puzzleElement equivalent puzzleElement - * @return a list of elements the specified could be - */ - @SuppressWarnings("unchecked") - @Override - public ArrayList getCases(Board board, PuzzleElement puzzleElement) { - - ShortTruthTableBoard sttBoard = ((ShortTruthTableBoard) board); - - ShortTruthTableCell cell = sttBoard.getCellFromElement(puzzleElement); - - //if the statement is set to true - if (cell.getType() == ShortTruthTableCellType.TRUE) { - return getCasesFromCell(sttBoard, puzzleElement, trueCases); - } - - //if the statement is set to false - return getCasesFromCell(sttBoard, puzzleElement, falseCases); - - } - - private ArrayList getCasesFromCell(ShortTruthTableBoard board, PuzzleElement puzzleElement, ShortTruthTableCellType[][] possibilities) { - - //store all possible boards - ArrayList cases = new ArrayList<>(); - - //go through all the possibilities - for (int i = 0; i < possibilities.length; i++) { - //create a new board - ShortTruthTableBoard b = board.copy(); - - //get the statement of the square that was selected - ShortTruthTableCell cell = b.getCellFromElement(puzzleElement); - ShortTruthTableStatement statement = cell.getStatementReference(); - - //modify its children - //avoid error if it is a NOT statement - if (possibilities[i][0] != null) { - ShortTruthTableCell leftCell = statement.getLeftStatement().getCell(); - leftCell.setData(possibilities[i][0]); - b.addModifiedData(leftCell); - } - - //always modify the right side of the statement - if (possibilities[i][1] != null) { - ShortTruthTableCell rightCell = statement.getRightStatement().getCell(); - rightCell.setData(possibilities[i][1]); - b.addModifiedData(rightCell); - } - - //add the board possibility to the list - cases.add(b); - } - - //return all possibilities - return cases; - - } - -} +package edu.rpi.legup.puzzle.shorttruthtable.rules.caserule; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.CaseBoard; +import edu.rpi.legup.model.gameboard.PuzzleElement; + +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCell; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableCellType; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableStatement; +import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableOperation; + + +import java.util.ArrayList; + +public abstract class CaseRule_GenericStatement extends CaseRule_Generic { + + public CaseRule_GenericStatement(String ruleID, char operation, String title, + ShortTruthTableCellType[][] trueCases, + ShortTruthTableCellType[][] falseCases) { + super(ruleID, ShortTruthTableOperation.getRuleName(operation), + title + " case", + "A known " + title.toUpperCase() + " statement can have multiple forms"); + + this.operation = operation; + + this.trueCases = trueCases; + this.falseCases = falseCases; + } + + private final char operation; + + private final ShortTruthTableCellType[][] trueCases; + private final ShortTruthTableCellType[][] falseCases; + + protected static final ShortTruthTableCellType T = ShortTruthTableCellType.TRUE; + protected static final ShortTruthTableCellType F = ShortTruthTableCellType.FALSE; + protected static final ShortTruthTableCellType U = ShortTruthTableCellType.UNKNOWN; + + // Adds all elements that can be selected for this caserule + @Override + public CaseBoard getCaseBoard(Board board) { + //copy the board and add all elements that can be selected + ShortTruthTableBoard sttBoard = (ShortTruthTableBoard) board.copy(); + sttBoard.setModifiable(false); + CaseBoard caseBoard = new CaseBoard(sttBoard, this); + + //add all elements that can be selected for the case rule statement + for (PuzzleElement element : sttBoard.getPuzzleElements()) { + //get the cell object + ShortTruthTableCell cell = sttBoard.getCellFromElement(element); + //the cell must match the symbol + if (cell.getSymbol() != this.operation) continue; + //the statement must be assigned with unassigned sub-statements + if (!cell.getType().isTrueOrFalse()) continue; + if (cell.getStatementReference().getRightStatement().getCell().getType().isTrueOrFalse()) continue; + if (this.operation != ShortTruthTableOperation.NOT && + cell.getStatementReference().getRightStatement().getCell().getType().isTrueOrFalse()) { + continue; + } + //if the element has passed all the checks, it can be selected + caseBoard.addPickableElement(element); + } + return caseBoard; + } + + /** + * Gets the possible cases at a specific location based on this case rule + * + * @param board the current board state + * @param puzzleElement equivalent puzzleElement + * @return a list of elements the specified could be + */ + @SuppressWarnings("unchecked") + @Override + public ArrayList getCases(Board board, PuzzleElement puzzleElement) { + ShortTruthTableBoard sttBoard = ((ShortTruthTableBoard) board); + ShortTruthTableCell cell = sttBoard.getCellFromElement(puzzleElement); + + // If the statement is set to true, collect true cases. Otherwise, collect the false cases + if (cell.getType() == ShortTruthTableCellType.TRUE) { + return getCasesFromCell(sttBoard, puzzleElement, trueCases); + } + return getCasesFromCell(sttBoard, puzzleElement, falseCases); + } + + /** + * Collects a list of boards for each possible outcome of case-rule application + * @param board current board state + * @param puzzleElement case rule operator + * @param possibilities list of possibilities for operator state + * @return ArrayList of Boards + */ + private ArrayList getCasesFromCell(ShortTruthTableBoard board, PuzzleElement puzzleElement, ShortTruthTableCellType[][] possibilities) { + // Create branch case for each possibility + ArrayList cases = new ArrayList<>(); + for (int i = 0; i < possibilities.length; i++) { + // Create a new board to modify and get statement of selected square + ShortTruthTableBoard b = board.copy(); + ShortTruthTableCell cell = b.getCellFromElement(puzzleElement); + ShortTruthTableStatement statement = cell.getStatementReference(); + + // Modify neighboring cells of case-rule application by the provided logical cases + if (possibilities[i][0] != ShortTruthTableCellType.UNKNOWN) { + ShortTruthTableCell leftCell = statement.getLeftStatement().getCell(); + leftCell.setData(possibilities[i][0]); + b.addModifiedData(leftCell); + } + if (possibilities[i][1] != ShortTruthTableCellType.UNKNOWN) { + ShortTruthTableCell rightCell = statement.getRightStatement().getCell(); + rightCell.setData(possibilities[i][1]); + b.addModifiedData(rightCell); + } + + cases.add(b); + } + return cases; + } +}