diff --git a/domain/src/main/kotlin/ch/dissem/yaep/domain/GameCell.kt b/domain/src/main/kotlin/ch/dissem/yaep/domain/GameCell.kt index 9b7b9e9..7e36c85 100644 --- a/domain/src/main/kotlin/ch/dissem/yaep/domain/GameCell.kt +++ b/domain/src/main/kotlin/ch/dissem/yaep/domain/GameCell.kt @@ -10,5 +10,6 @@ class GameCell>( // var selection by mutableStateOf(selection) //} -fun > GameCell?.mayBe(item: Item) = - this != null && (selection == item || (selection == null && options.contains(item))) +fun > GameCell?.mayBe(item: Item, mayHaveSelection: Boolean = true) = + this != null && + ((mayHaveSelection && selection == item) || (selection == null && options.contains(item))) diff --git a/domain/src/main/kotlin/ch/dissem/yaep/domain/clues.kt b/domain/src/main/kotlin/ch/dissem/yaep/domain/clues.kt index 1f62b6b..efa90c5 100644 --- a/domain/src/main/kotlin/ch/dissem/yaep/domain/clues.kt +++ b/domain/src/main/kotlin/ch/dissem/yaep/domain/clues.kt @@ -114,9 +114,9 @@ class OrderClue, R : ItemClass>(val left: Item, val right var removed = false try { - rowL.takeLast(rowL.size - lastR + 1) + rowL.takeLast(rowL.size - lastR) .forEach { removed = it.options.remove(left) || removed } - rowR.take(firstL).forEach { removed = it.options.remove(right) || removed } + rowR.take(firstL + 1).forEach { removed = it.options.remove(right) || removed } } catch (e: IllegalArgumentException) { throw UnsolvablePuzzleException(e) } @@ -216,7 +216,54 @@ class TripletClue, B : ItemClass, C : ItemClass>( } override fun removeForbiddenOptions(grid: Grid): Boolean { - TODO("Not yet implemented") + val rowA = grid[aType.companion] + val rowB = grid[bType.companion] + val rowC = grid[cType.companion] + + var removed = false + + for (i in rowA.indices) { + val cellA = rowA[i] + if (cellA.mayBe(a, mayHaveSelection = false)) { + val cellBR = rowB.getOrNull(i + 1) + val cellCR = rowC.getOrNull(i + 2) + val cellBL = rowB.getOrNull(i - 1) + val cellCL = rowC.getOrNull(i - 2) + + if (!(cellBR.mayBe(b) && cellCR.mayBe(c)) && !(cellBL.mayBe(b) && cellCL.mayBe(c))) { + removed = cellA.options.remove(a) || removed + } + } + } + for (i in rowB.indices) { + val cellB = rowB[i] + if (cellB.mayBe(b, mayHaveSelection = false)) { + val cellAL = rowA.getOrNull(i - 1) + val cellAR = rowA.getOrNull(i + 1) + val cellCL = rowC.getOrNull(i - 1) + val cellCR = rowC.getOrNull(i + 1) + + if (!(cellAL.mayBe(a) && cellCR.mayBe(c)) && !(cellCL.mayBe(c) && cellAR.mayBe(a))) { + removed = cellB.options.remove(b) || removed + } + } + } + + for (i in rowC.indices) { + val cellC = rowC[i] + if (cellC.mayBe(c, mayHaveSelection = false)) { + val cellBR = rowB.getOrNull(i + 1) + val cellAR = rowA.getOrNull(i + 2) + val cellBL = rowB.getOrNull(i - 1) + val cellAL = rowA.getOrNull(i - 2) + + if (!(cellBR.mayBe(b) && cellAR.mayBe(a)) && !(cellBL.mayBe(b) && cellAL.mayBe(a))) { + removed = cellC.options.remove(c) || removed + } + } + } + + return removed } override fun toString(): String =