clone

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

updated tape files with set seed. eventually wanna make the gameplay not random input.

Dami committed cfe1c31
commit
cfe1c313f7ad127acc5ba79596ffee47ef72a6f4
parent
31aba7fdb0740572e0f5f60658a9afa02c33604f
author
Dami <dami.etoile@gmail.com>
16 files changed, +50 -21
MAGENTS.md8++++++++
MREADME.md6+++++-
Mcmd/new.go25+++++++++++++++++++++----
Mcmd/root.go2+-
Mvhs/hashiwokakero.tape2+-
Mvhs/help.tape2+-
Mvhs/hitori.tape2+-
Mvhs/lightsout.tape2+-
Mvhs/menu.tape2+-
Mvhs/nonogram.tape6+++---
Mvhs/nurikabe.tape2+-
Mvhs/shikaku.tape2+-
Mvhs/stats.tape2+-
Mvhs/sudoku.tape2+-
Mvhs/takuzu.tape2+-
Mvhs/wordsearch.tape4++--
M AGENTS.md +8 -0
M README.md +5 -1
M cmd/new.go +21 -4
@@ -6,6 +6,7 @@ import (
66 77 "github.com/FelineStateMachine/puzzletea/app"88 "github.com/FelineStateMachine/puzzletea/config"9+ "github.com/FelineStateMachine/puzzletea/game"910 "github.com/FelineStateMachine/puzzletea/namegen"1011 "github.com/FelineStateMachine/puzzletea/resolve"1112 "github.com/FelineStateMachine/puzzletea/stats"
@@ -14,7 +15,10 @@ import (
1415 "github.com/spf13/cobra"1516 )1617 17-var flagSetSeed string18+var (19+ flagSetSeed string20+ flagWithSeed string21+)1822 1923 var newCmd = &cobra.Command{2024 Use: "new <game> [mode]",
@@ -40,16 +44,17 @@ var newCmd = &cobra.Command{
4044 if len(args) > 1 {4145 modeArg = args[1]4246 }43- return launchNewGame(gameArg, modeArg, cfg)47+ return launchNewGame(gameArg, modeArg, flagWithSeed, cfg)4448 },4549 }4650 4751 func init() {4852 newCmd.Flags().StringVar(&flagSetSeed, "set-seed", "", "seed string for deterministic puzzle selection and generation")53+ newCmd.Flags().StringVar(&flagWithSeed, "with-seed", "", "seed string for deterministic puzzle generation within the selected game/mode")4954 }5055 5156 // launchNewGame resolves the game/mode, spawns a new game, and launches the TUI.52-func launchNewGame(gameArg, modeArg string, cfg *config.Config) error {57+func launchNewGame(gameArg, modeArg, seed string, cfg *config.Config) error {5358 cat, err := resolve.Category(gameArg, app.GameCategories)5459 if err != nil {5560 return err
@@ -60,7 +65,7 @@ func launchNewGame(gameArg, modeArg string, cfg *config.Config) error {
6065 return err6166 }6267 63- g, err := spawner.Spawn()68+ g, err := spawnFromMode(spawner, seed)6469 if err != nil {6570 return fmt.Errorf("failed to spawn game: %w", err)6671 }
@@ -84,6 +89,18 @@ func launchNewGame(gameArg, modeArg string, cfg *config.Config) error {
8489 return runGameProgram(s, cfg, g, rec.ID, false)8590 }8691 92+func spawnFromMode(spawner game.Spawner, seed string) (game.Gamer, error) {93+ if seed == "" {94+ return spawner.Spawn()95+ }96+97+ seeded, ok := spawner.(game.SeededSpawner)98+ if !ok {99+ return nil, fmt.Errorf("mode does not support deterministic spawning")100+ }101+ return seeded.SpawnSeeded(resolve.RNGFromString(seed))102+}103+87104 // launchSeededGame uses an arbitrary seed string to deterministically select88105 // a game type, mode, and puzzle. The same seed always produces the same puzzle.89106 // If a game with the same seed-derived name already exists, it is resumed.
M cmd/root.go +1 -1
M vhs/hashiwokakero.tape +1 -1
M vhs/help.tape +1 -1
M vhs/hitori.tape +1 -1
M vhs/lightsout.tape +1 -1
M vhs/menu.tape +1 -1
M vhs/nonogram.tape +3 -3
M vhs/nurikabe.tape +1 -1
M vhs/shikaku.tape +1 -1
M vhs/stats.tape +1 -1
M vhs/sudoku.tape +1 -1
M vhs/takuzu.tape +1 -1
M vhs/wordsearch.tape +2 -2