Skip to content

Commit

Permalink
Finish reworking X Within Y rules
Browse files Browse the repository at this point in the history
  • Loading branch information
summerhenson committed Aug 6, 2024
1 parent 54184df commit 2d0026e
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
int columnStars = 0;
int regionStars = 0;
for (int c: columnSubset) {
columnStars += board.columnStars(c);
columnStars += origBoard.columnStars(c);
for (StarBattleCell ce: origBoard.getCol(c)) {
if (ce.getType() == StarBattleCellType.UNKNOWN) {
if (regions.add(ce.getGroupIndex())) {
regionStars += board.getRegion(ce.getGroupIndex()).numStars();
regionStars += origBoard.getRegion(ce.getGroupIndex()).numStars();
}
if (ce.getGroupIndex() == region) {
containsRegion = true;
Expand All @@ -89,64 +89,7 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
return null;
}
}
/*
//StarBattleBoard modified = (StarBattleBoard) origBoard.copy();
//modified.getPuzzleElement(puzzleElement).setData(StarBattleCellType.BLACK.value);
// the columns that are contained
Set<Integer> columns = new HashSet<Integer>();
// the regions that contain them
Set<Integer> regions = new HashSet<Integer>();
// columns and regions to process
List<Integer> columnsToCheck = new ArrayList<Integer>();
List<Integer> regionsToCheck = new ArrayList<Integer>();
int columnStars = 0;
int regionStars = 0;
regions.add(cell.getGroupIndex());
regionsToCheck.add(cell.getGroupIndex());
while (!columnsToCheck.isEmpty() || !regionsToCheck.isEmpty()) {
for (int i = 0; i < regionsToCheck.size(); ++i) {
int r = regionsToCheck.get(i);
regionStars += board.getRegion(r).numStars();
for (StarBattleCell c : board.getRegion(r).getCells()) {
int column = ((StarBattleCell) c).getLocation().x;
if (column != cell.getLocation().x && c.getType() == StarBattleCellType.UNKNOWN && columns.add(column)) {
columnsToCheck.add(column);
}
}
regionsToCheck.remove(i);
--i;
}
for (int j = 0; j < columnsToCheck.size(); ++j) {
int c = columnsToCheck.get(j);
columnStars += board.columnStars(c);
for (int i = 0; i < board.getSize(); ++i) {
int region = board.getCell(c, i).getGroupIndex();
if (board.getCell(c,i).getType() == StarBattleCellType.UNKNOWN && regions.add(region)) {
regionsToCheck.add(region);
}
}
columnsToCheck.remove(j);
--j;
}
}
// are the columns and regions missing an equal amount of stars
if (board.getPuzzleNumber() * columns.size() - columnStars
!= board.getPuzzleNumber() * regions.size() - regionStars) {
return "The number of missing stars in the columns and regions must be equal and every extraneous cell must be black!";
}
if (columns.contains(cell.getLocation().x)) {
return "Only black out cells outside the column(s)!";
}
/*
for (int c: columns) {
if (c == cell.getLocation().x) {
return "Only black out cells outside the column(s)!";
}
}
*/
return "Wrong!";
return "The columns must fully fit within regions with the same number of stars missing!";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
import edu.rpi.legup.puzzle.starbattle.StarBattleCell;
import edu.rpi.legup.puzzle.starbattle.StarBattleCellType;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

public class ColumnsWithinRowsDirectRule extends DirectRule {

Expand All @@ -24,6 +21,25 @@ public ColumnsWithinRowsDirectRule() {
"edu/rpi/legup/images/starbattle/rules/ColumnsWithinRowsDirectRule.png");
}

private void generateSubsets(List<List<Integer>> subsets, int current, int skip, int size) {
if (current == size) {
return;
}
List<List<Integer>> newSubsets = new LinkedList<List<Integer>>();
if (current != skip) {
for (List<Integer> subset: subsets) {
List<Integer> copy = new LinkedList<Integer>(subset);
copy.add(current);
newSubsets.add(copy);
}
subsets.addAll(newSubsets);
List<Integer> oneMember = new LinkedList<Integer>();
oneMember.add(current);
subsets.add(oneMember);
}
generateSubsets(subsets, current + 1 == skip ? current + 2 : current + 1, skip, size);
}

/**
* Checks whether the child node logically follows from the parent node at the specific
* puzzleElement index using this rule
Expand All @@ -39,59 +55,43 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
// assumption: the rule has been applied to its fullest extent and the rows and columns
// are now mutually encompassing
StarBattleBoard board = (StarBattleBoard) transition.getBoard();
StarBattleBoard origBoard = (StarBattleBoard) transition.getParents().get(0).getBoard();
StarBattleCell cell = (StarBattleCell) board.getPuzzleElement(puzzleElement);
int dim = board.getSize();
int row = cell.getLocation().y;
int column = cell.getLocation().x;

if (cell.getType() != StarBattleCellType.BLACK) {
return "Only black cells are allowed for this rule!";
}

// the columns that are contained
Set<Integer> columns = new HashSet<Integer>();
// the rows that contain them
Set<Integer> rows = new HashSet<Integer>();
// columns and rows to process
List<Integer> columnsToCheck = new ArrayList<Integer>();
List<Integer> rowsToCheck = new ArrayList<Integer>();
int columnStars = 0;
int rowStars = 0;
int firstRow = cell.getLocation().y;
rows.add(firstRow);
rowsToCheck.add(firstRow);
List<List<Integer>> subsets = new LinkedList<List<Integer>>();
generateSubsets(subsets,0, column, dim);

while (!columnsToCheck.isEmpty() || !rowsToCheck.isEmpty()) {
for (int i = 0; i < rowsToCheck.size(); ++i) {
int r = rowsToCheck.get(i);
rowStars += board.rowStars(r);
for (StarBattleCell c : board.getRow(r)) {
int column = c.getLocation().x;
if (c.getType() == StarBattleCellType.UNKNOWN && columns.add(column)) {
columnsToCheck.add(column);
for (List<Integer> columnSubset: subsets) {
Set<Integer> rows = new HashSet<Integer>();
boolean containsRow = false;
int columnStars = 0;
int rowStars = 0;
for (int c: columnSubset) {
columnStars += origBoard.columnStars(c);
for (StarBattleCell ce: origBoard.getCol(c)) {
if (ce.getType() == StarBattleCellType.UNKNOWN) {
if (rows.add(ce.getLocation().y)) {
rowStars += origBoard.rowStars(ce.getLocation().y);
}
if (ce.getLocation().y == row) {
containsRow = true;
}
}
}
rowsToCheck.remove(i);
--i;
}
for (int i = 0; i < columnsToCheck.size(); ++i) {
int c = columnsToCheck.get(i);
columnStars += board.columnStars(c);
for (StarBattleCell r : board.getCol(c)) {
int row = r.getLocation().y;
if (r.getType() == StarBattleCellType.UNKNOWN && rows.add(row)) {
rowsToCheck.add(row);
}
}
columnsToCheck.remove(i);
--i;
if (containsRow && board.getPuzzleNumber() * columnSubset.size() - columnStars
>= board.getPuzzleNumber() * rows.size() - rowStars) {
return null;
}
}
// are the columns and regions missing an equal amount of stars
if (board.getPuzzleNumber() * columns.size() - columnStars
!= board.getPuzzleNumber() * rows.size() - rowStars) {
return "The number of missing stars in the columns and rows must be equal and every extraneous cell must be black!";
}
if (columns.contains(cell.getLocation().x)) {
return "Only black out cells outside the column(s)!";
}
return null;
return "The columns must fully fit within rows with the same number of stars missing!";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public RegionsWithinColumnsDirectRule() {
public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
ColumnsWithinRegionsDirectRule correspondingRule = new ColumnsWithinRegionsDirectRule();
String result = correspondingRule.checkRuleRawAt(transition, puzzleElement);
if (result != null && result.equals("Only black out cells outside the column(s)!")) {
return "Only black out cells outside the region(s)!";
if (result != null && result.equals("The columns must fully fit within regions with the same number of stars missing!")) {
return "The regions must fully fit within columns with the same number of stars missing!";
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem

RowsWithinRegionsDirectRule correspondingRule = new RowsWithinRegionsDirectRule();
String result = correspondingRule.checkRuleRawAt(transition, puzzleElement);
if (result != null && result.equals("Only black out cells outside the row(s)!")) {
return "Only black out cells outside the region(s)!";
if (result != null && result.equals("The rows must fully fit within regions with the same number of stars missing!")) {
return "The regions must fully fit within rows with the same number of stars missing!";
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem

ColumnsWithinRowsDirectRule correspondingRule = new ColumnsWithinRowsDirectRule();
String result = correspondingRule.checkRuleRawAt(transition, puzzleElement);
if (result != null && result.equals("Only black out cells outside the column(s)!")) {
return "Only black out cells outside the row(s)!";
if (result != null && result.equals("The columns must fully fit within rows with the same number of stars missing!")) {
return "The rows must fully fit within columns with the same number of stars missing!";
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
import edu.rpi.legup.puzzle.starbattle.StarBattleCell;
import edu.rpi.legup.puzzle.starbattle.StarBattleCellType;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

public class RowsWithinRegionsDirectRule extends DirectRule {
public RowsWithinRegionsDirectRule() {
Expand All @@ -23,6 +20,25 @@ public RowsWithinRegionsDirectRule() {
"edu/rpi/legup/images/starbattle/rules/RowsWithinRegionsDirectRule.png");
}

private void generateSubsets(List<List<Integer>> subsets, int current, int skip, int size) {
if (current == size) {
return;
}
List<List<Integer>> newSubsets = new LinkedList<List<Integer>>();
if (current != skip) {
for (List<Integer> subset: subsets) {
List<Integer> copy = new LinkedList<Integer>(subset);
copy.add(current);
newSubsets.add(copy);
}
subsets.addAll(newSubsets);
List<Integer> oneMember = new LinkedList<Integer>();
oneMember.add(current);
subsets.add(oneMember);
}
generateSubsets(subsets, current + 1 == skip ? current + 2 : current + 1, skip, size);
}

/**
* Checks whether the child node logically follows from the parent node at the specific
* puzzleElement index using this rule
Expand All @@ -38,10 +54,45 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
// assumption: the rule has been applied to its fullest extent and the rows and regions
// are now mutually encompassing
StarBattleBoard board = (StarBattleBoard) transition.getBoard();
StarBattleBoard origBoard = (StarBattleBoard) transition.getParents().get(0).getBoard();
StarBattleCell cell = (StarBattleCell) board.getPuzzleElement(puzzleElement);
int dim = board.getSize();
int region = cell.getGroupIndex();
int row = cell.getLocation().y;

if (cell.getType() != StarBattleCellType.BLACK) {
return "Only black cells are allowed for this rule!";
}

List<List<Integer>> subsets = new LinkedList<List<Integer>>();
generateSubsets(subsets,0, row, dim);

for (List<Integer> rowSubset: subsets) {
Set<Integer> regions = new HashSet<Integer>();
boolean containsRegion = false;
int rowStars = 0;
int regionStars = 0;
for (int r: rowSubset) {
rowStars += origBoard.rowStars(r);
for (StarBattleCell ce: origBoard.getRow(r)) {
if (ce.getType() == StarBattleCellType.UNKNOWN) {
if (regions.add(ce.getGroupIndex())) {
regionStars += origBoard.getRegion(ce.getGroupIndex()).numStars();
}
if (ce.getGroupIndex() == region) {
containsRegion = true;
}
}
}
}
if (containsRegion && board.getPuzzleNumber() * rowSubset.size() - rowStars
>= board.getPuzzleNumber() * regions.size() - regionStars) {
return null;
}
}
return "The rows must fully fit within regions with the same number of stars missing!";

/*
// the rows that are contained
Set<Integer> rows = new HashSet<Integer>();
// the regions that contain them
Expand Down Expand Up @@ -89,6 +140,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
return "Only black out cells outside the row(s)!";
}
return null;
*/
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public void ColumnsWithinRowsDirectRule_FalseColumnsWithinRows1()
}

@Test
public void ColumnsWithinRowsDirectRule_FalseColumnsWithinRows2()
public void ColumnsWithinRowsDirectRule_PartialCover()
throws InvalidFileFormatException {
TestUtilities.importTestBoard("puzzles/starbattle/rules/ColumnsWithinRowsDirectRule/OneColumn", starbattle);
TreeNode rootNode = starbattle.getTree().getRootNode();
Expand All @@ -203,11 +203,18 @@ public void ColumnsWithinRowsDirectRule_FalseColumnsWithinRows2()
cell1.setData(StarBattleCellType.BLACK.value);
board.addModifiedData(cell1);

Assert.assertNotNull(RULE.checkRule(transition));
Assert.assertNull(RULE.checkRule(transition));

Point location = new Point(1,0);
for (int i = 0; i < board.getHeight(); i++) {
for (int k = 0; k < board.getWidth(); k++) {
Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i)));
Point point = new Point(k,i);
if (point.equals(location)) {
Assert.assertNull(RULE.checkRuleAt(transition, board.getCell(k, i)));
}
else {
Assert.assertNotNull(RULE.checkRuleAt(transition, board.getCell(k, i)));
}
}
}
}
Expand Down

0 comments on commit 2d0026e

Please sign in to comment.