clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

tweaked nurikabe to be more reasonably difficult/generation speed trade of

Dami committed d260f2e
commit
d260f2e00012bf3d2207281fc8b6b2c3d1ca48ed
parent
04734451ee053244591c0de01e258e0a9fff5e1e
author
Dami <dami.etoile@gmail.com>
2 files changed, +50 -7
Mnurikabe/generator.go38+++++++++++++++++++++++++++---
Mnurikabe/nurikabe_test.go19+++++++++++++--
M nurikabe/generator.go +34 -4
@@ -14,6 +14,7 @@ import (
1414 const (1515 generationHardTimeout = 10 * time.Second1616 uniquenessMinRemainingBudget = 250 * time.Millisecond17+ frontierBiasSampleCount = 71718 )1819 1920 type generationBudget struct {
@@ -677,12 +678,41 @@ func (s *candidateState) popFrontier(rng *rand.Rand) (point, bool) {
677678 if len(s.frontier) == 0 {678679 return point{}, false679680 }680- idx := rng.IntN(len(s.frontier))681- picked := s.frontier[idx]681+682+ bestIdx := -1683+ bestScore := -1684+ samples := min(frontierBiasSampleCount, len(s.frontier))685+ for range samples {686+ idx := rng.IntN(len(s.frontier))687+ score := s.frontierPriorityScore(s.frontier[idx])688+ if score > bestScore || (score == bestScore && rng.IntN(2) == 0) {689+ bestScore = score690+ bestIdx = idx691+ }692+ }693+694+ if bestIdx < 0 {695+ bestIdx = rng.IntN(len(s.frontier))696+ }697+698+ picked := s.frontier[bestIdx]682699 s.removeFrontier(picked)683700 return picked, true684701 }685702 703+func (s *candidateState) frontierPriorityScore(p point) int {704+ if !s.inBounds(p) || s.sea[p.y][p.x] {705+ return 0706+ }707+708+ label := s.labels[p.y][p.x]709+ componentSize := s.componentSize[label]710+ sameLabelNeighbors := len(s.landNeighborsWithLabel(p, label))711+712+ // Favor carving from larger components; local degree nudges toward useful splits.713+ return componentSize*16 + sameLabelNeighbors*3714+}715+686716 func (s *candidateState) removeComponent(label int) {687717 size, ok := s.componentSize[label]688718 if !ok {
@@ -1048,7 +1078,7 @@ func modeIslandProfile(mode NurikabeMode) islandProfile {
10481078 minAverageSize: 1.8,10491079 maxSingletonRatio: 0.72,10501080 minLargestIsland: 4,1051- maxLargestIsland: 20,1081+ maxLargestIsland: 15,10521082 }10531083 case "Expert":10541084 return islandProfile{
@@ -1059,7 +1089,7 @@ func modeIslandProfile(mode NurikabeMode) islandProfile {
10591089 minAverageSize: 1.7,10601090 maxSingletonRatio: 0.78,10611091 minLargestIsland: 4,1062- maxLargestIsland: 22,1092+ maxLargestIsland: 17,10631093 }10641094 default:10651095 return islandProfile{
M nurikabe/nurikabe_test.go +16 -3