clone

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

feat/app-decomposition
puzzletea / games / netwalk / gamemode.go
gamemode.go 3.3K
1package netwalk23import (4 _ "embed"5 "math/rand/v2"67 "github.com/FelineStateMachine/puzzletea/game"8 "github.com/FelineStateMachine/puzzletea/gameentry"9 "github.com/FelineStateMachine/puzzletea/puzzle"10)1112//go:embed help.md13var HelpContent string1415type NetwalkMode struct {16 game.BaseMode17 Size int18 FillRatio float6419 Profile generateProfile20}2122var (23 _ game.Mode = NetwalkMode{}24 _ game.Spawner = NetwalkMode{}25 _ game.SeededSpawner = NetwalkMode{}26)2728func NewMode(title, desc string, size int, fillRatio float64, profile generateProfile) NetwalkMode {29 return NetwalkMode{30 BaseMode: game.NewBaseMode(title, desc),31 Size: size,32 FillRatio: fillRatio,33 Profile: profile,34 }35}3637func (m NetwalkMode) Spawn() (game.Gamer, error) {38 p, err := GenerateSeededWithDensity(39 m.Size,40 m.FillRatio,41 m.Profile,42 rand.New(rand.NewPCG(rand.Uint64(), rand.Uint64())),43 )44 if err != nil {45 return nil, err46 }47 return New(m, p)48}4950func (m NetwalkMode) SpawnSeeded(rng *rand.Rand) (game.Gamer, error) {51 p, err := GenerateSeededWithDensity(m.Size, m.FillRatio, m.Profile, rng)52 if err != nil {53 return nil, err54 }55 return New(m, p)56}5758var (59 miniProfile = generateProfile{60 ParentDegreeWeights: [5]int{16, 16, 6, -8, -12},61 OrthogonalPackedWeight: 2,62 DiagonalPackedWeight: 1,63 SpanGrowthWeight: 12,64 MinSpanRatio: 0.55,65 }66 easyProfile = generateProfile{67 ParentDegreeWeights: [5]int{14, 14, 8, -4, -8},68 OrthogonalPackedWeight: 4,69 DiagonalPackedWeight: 2,70 SpanGrowthWeight: 14,71 MinSpanRatio: 0.62,72 }73 mediumProfile = generateProfile{74 ParentDegreeWeights: [5]int{10, 10, 12, 2, -4},75 OrthogonalPackedWeight: 6,76 DiagonalPackedWeight: 3,77 SpanGrowthWeight: 14,78 MinSpanRatio: 0.70,79 }80 hardProfile = generateProfile{81 ParentDegreeWeights: [5]int{6, 6, 16, 8, 0},82 OrthogonalPackedWeight: 8,83 DiagonalPackedWeight: 4,84 SpanGrowthWeight: 16,85 MinSpanRatio: 0.78,86 }87 expertProfile = generateProfile{88 ParentDegreeWeights: [5]int{4, 4, 18, 10, 2},89 OrthogonalPackedWeight: 10,90 DiagonalPackedWeight: 5,91 SpanGrowthWeight: 18,92 MinSpanRatio: 0.84,93 }94)9596var Modes = []game.Mode{97 NewMode("Mini 5x5", "Compact 5×5 network with a denser starter tree.", 5, 0.50, miniProfile),98 NewMode("Easy 7x7", "7×7 board with fuller coverage and gentle local tangles.", 7, 0.57, easyProfile),99 NewMode("Medium 9x9", "Balanced 9×9 network with tighter clusters and more branching.", 9, 0.64, mediumProfile),100 NewMode("Hard 11x11", "Dense 11×11 board that packs branches into close local interactions.", 11, 0.72, hardProfile),101 NewMode("Expert 13x13", "Large, crowded network with heavy branching and frequent near-miss tangles.", 13, 0.78, expertProfile),102}103104var ModeDefinitions = gameentry.BuildModeDefs(Modes)105106var Definition = puzzle.NewDefinition(puzzle.DefinitionSpec{107 Name: "Netwalk",108 Description: "Rotate network tiles until every computer connects to the server.",109 Aliases: []string{"network"},110 Modes: ModeDefinitions,111 DailyModeIDs: puzzle.SelectModeIDsByIndex(ModeDefinitions, 1, 2),112})113114var Entry = gameentry.NewEntry(gameentry.EntrySpec{115 Definition: Definition,116 Help: HelpContent,117 Import: game.AdaptImport(ImportModel),118 Modes: Modes,119 Print: PDFPrintAdapter,120})