clone

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

bug/architecture-test-trim-path
puzzletea / games / nonogram / gamemode.go
gamemode.go 2.9K
1package nonogram23import (4 _ "embed"5 "math/rand/v2"67 "github.com/FelineStateMachine/puzzletea/difficulty"8 "github.com/FelineStateMachine/puzzletea/game"9 "github.com/FelineStateMachine/puzzletea/gameentry"10 "github.com/FelineStateMachine/puzzletea/puzzle"11)1213//go:embed help.md14var HelpContent string1516type NonogramMode struct {17 game.BaseMode18 Width, Height int19 Density float64 // target fill percentage, 0.0–1.020}2122var (23 _ game.Mode = NonogramMode{}24 _ game.Spawner = NonogramMode{}25 _ game.SeededSpawner = NonogramMode{}26 _ game.EloSpawner = NonogramMode{}27)2829func NewMode(title, description string, width, height int, density float64) NonogramMode {30 return NonogramMode{31 BaseMode: game.NewBaseMode(title, description),32 Width: width,33 Height: height,34 Density: density,35 }36}3738func (n NonogramMode) Spawn() (game.Gamer, error) {39 hints := GenerateRandomTomography(n)40 return New(n, hints)41}4243func (n NonogramMode) SpawnSeeded(rng *rand.Rand) (game.Gamer, error) {44 hints := GenerateRandomTomographySeeded(n, rng)45 return New(n, hints)46}4748var Modes = []game.Mode{49 // 5x550 NewMode("Mini", "5x5 grid, ~65% filled. Quick puzzle, straightforward hints.", 5, 5, 0.65),51 NewMode("Pocket", "5x5 grid, ~50% filled. Compact but balanced.", 5, 5, 0.50),52 NewMode("Teaser", "5x5 grid, ~35% filled. Small but tricky.", 5, 5, 0.35),53 // 10x1054 NewMode("Standard", "10x10 grid, ~67% filled. Classic size, dense hints.", 10, 10, 0.67),55 NewMode("Classic", "10x10 grid, ~52% filled. The typical nonogram experience.", 10, 10, 0.52),56 NewMode("Tricky", "10x10 grid, ~37% filled. Sparse hints require reasoning.", 10, 10, 0.37),57 // 15x1558 NewMode("Large", "15x15 grid, ~69% filled. Bigger grid, constraining hints.", 15, 15, 0.69),59 NewMode("Grand", "15x15 grid, ~54% filled. A substantial challenge.", 15, 15, 0.54),60 // 20x2061 NewMode("Epic", "20x20 grid, ~71% filled. A epic undertaking.", 20, 20, 0.71),62 NewMode("Massive", "20x20 grid, ~56% filled. Truly massive puzzle.", 20, 20, 0.56),63}6465var ModeDefinitions = nonogramModeDefinitions(Modes)6667func nonogramModeDefinitions(modes []game.Mode) []puzzle.ModeDef {68 defs := gameentry.BuildModeDefs(modes)69 presets := []difficulty.Elo{100, 450, 800, 1000, 1300, 1600, 1900, 2200, 2600, 2900}70 for i, mode := range modes {71 if i >= len(defs) || i >= len(presets) {72 break73 }74 if _, ok := mode.(game.EloSpawner); !ok {75 continue76 }77 elo := presets[i]78 defs[i].PresetElo = &elo79 }80 return defs81}8283var Definition = puzzle.NewDefinition(puzzle.DefinitionSpec{84 Name: "Nonogram",85 Description: "Fill the cells to match tomographic hints.",86 Modes: ModeDefinitions,87 DailyModeIDs: puzzle.SelectModeIDsByIndex(ModeDefinitions, 3, 4),88})8990var Entry = gameentry.NewEntry(gameentry.EntrySpec{91 Definition: Definition,92 Help: HelpContent,93 Import: game.AdaptImport(ImportModel),94 Modes: Modes,95 Print: PDFPrintAdapter,96})