Skip to content

Commit

Permalink
Implements difficulty choosing with the new calculation algorithm
Browse files Browse the repository at this point in the history
Enabled in debug variant only. Calculates the minimum amount of cages to hopefully match the desired difficulty.
  • Loading branch information
meikpiep committed Jan 5, 2025
1 parent 9b50b58 commit 614ac40
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class GridCellOptionsFragment :
val variant = viewModel.gameVariantState.value

val difficultyOrNull =
if (viewModel.difficultyClassificationAvailable() && variant.variant.options.difficultySetting != DifficultySetting.ANY) {
if (variant.variant.options.difficultySetting != DifficultySetting.ANY) {
variant.variant.options.difficultySetting.gameDifficulty
} else {
null
Expand Down Expand Up @@ -268,7 +268,6 @@ class GridCellOptionsFragment :
}

private fun gameVariantChanged() {
binding.difficultyChipGroup.forEach { it.isEnabled = viewModel.difficultyClassificationAvailable() }
binding.singleCellUsageChipGroup.forEach { it.isEnabled = viewModel.singleCellOptionsAvailable() }

val numbersBadgeShouldBeVisible =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ import org.piepmeyer.gauguin.difficulty.GridDifficultyCalculator
import org.piepmeyer.gauguin.grid.Grid
import org.piepmeyer.gauguin.grid.GridCage
import org.piepmeyer.gauguin.grid.GridCell
import org.piepmeyer.gauguin.options.DifficultySetting
import org.piepmeyer.gauguin.options.GameVariant
import kotlin.coroutines.coroutineContext
import kotlin.math.abs
import kotlin.math.round
import kotlin.time.measureTime
import kotlin.time.measureTimedValue

private val logger = KotlinLogging.logger {}

class MergingCageGridCalculator(
private val variant: GameVariant,
val variant: GameVariant,
private val randomizer: Randomizer = RandomSingleton.instance,
private val shuffler: PossibleDigitsShuffler = RandomPossibleDigitsShuffler(),
) : GridCalculator {
Expand All @@ -42,11 +44,12 @@ class MergingCageGridCalculator(
var newGrid = grid

var singleCageMerges = 0
val minimumCageSize = minimumCageSize()

logger.info { "Start merging with single cages..." }
val mergeWithSingles =
measureTime {
while (runsWithoutSuccess < 3) {
while (runsWithoutSuccess < 3 && newGrid.cages.size > minimumCageSize) {
val (lastSuccess, lastGrid) = mergeSingleCageWithCage(newGrid)

if (lastSuccess) {
Expand All @@ -61,14 +64,28 @@ class MergingCageGridCalculator(
}
logger.info { "Finished merging with single cages" }

runsWithoutSuccess = 0
if (newGrid.cages.size == minimumCageSize) {
logger.info { "Start merging single cages only..." }
while (runsWithoutSuccess < 3) {
val (lastSuccess, lastGrid) = mergeSingleCages(newGrid)

if (lastSuccess) {
newGrid = lastGrid
runsWithoutSuccess = 0
} else {
runsWithoutSuccess++
}
}
logger.info { "Finished merging single cages only" }
}

runsWithoutSuccess = 0
var multiCageMerges = 0

logger.info { "Start merging non-single cages..." }
val mergeNonSingles =
measureTime {
while (runsWithoutSuccess < 3) {
while (runsWithoutSuccess < 3 && newGrid.cages.size > minimumCageSize) {
val (lastSuccess, lastGrid) = mergeCages(newGrid)

if (lastSuccess) {
Expand Down Expand Up @@ -97,6 +114,20 @@ class MergingCageGridCalculator(
return newGrid
}

private fun minimumCageSize(): Int {
val maximumAverageCageCells =
when (variant.options.difficultySetting) {
DifficultySetting.VERY_EASY -> 2.025
DifficultySetting.EASY -> 2.31
DifficultySetting.MEDIUM -> 2.61
DifficultySetting.HARD -> 3.0
DifficultySetting.EXTREME -> Double.MAX_VALUE
DifficultySetting.ANY -> 2.025 + ((3.375 - 2.025) * randomizer.nextDouble())
}

return round(variant.surfaceArea.toDouble() / maximumAverageCageCells).toInt()
}

private suspend fun mergeCages(grid: Grid): Pair<Boolean, Grid> {
val cages = grid.cages

Expand All @@ -115,6 +146,24 @@ class MergingCageGridCalculator(
return Pair(false, grid)
}

private suspend fun mergeSingleCages(grid: Grid): Pair<Boolean, Grid> {
val singleCages = grid.cages.filter { it.cells.size == 1 }

singleCages.shuffled(randomizer.random()).forEach { cage ->
singleCages.shuffled(randomizer.random()).forEach { otherCage ->
if (cage != otherCage && grid.areAdjacent(cage, otherCage) && cage.cells.size + otherCage.cells.size <= 4) {
val newGrid = tryMergingCages(grid, cage, otherCage, "Merge non-single cages")

if (newGrid != null) {
return Pair(true, newGrid)
}
}
}
}

return Pair(false, grid)
}

private suspend fun mergeSingleCageWithCage(grid: Grid): Pair<Boolean, Grid> {
val singleCages = grid.cages.filter { it.cells.size == 1 }
val cages = grid.cages
Expand Down

0 comments on commit 614ac40

Please sign in to comment.