clone

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

chore/app-model-decomp
puzzletea / games / nurikabe / export.go
export.go 1.8K
1package nurikabe23import (4 "encoding/json"5 "fmt"67 "github.com/FelineStateMachine/puzzletea/game"8)910type Save struct {11 Width int `json:"width"`12 Height int `json:"height"`13 Clues string `json:"clues"`14 Marks string `json:"marks"`15 ModeTitle string `json:"mode_title"`16}1718func (m Model) GetSave() ([]byte, error) {19 save := Save{20 Width: m.width,21 Height: m.height,22 Clues: serializeClues(m.clues),23 Marks: m.marks.String(),24 ModeTitle: m.modeTitle,25 }26 data, err := json.Marshal(save)27 if err != nil {28 return nil, fmt.Errorf("failed to marshal nurikabe save: %w", err)29 }30 return data, nil31}3233func ImportModel(data []byte) (*Model, error) {34 var s Save35 if err := json.Unmarshal(data, &s); err != nil {36 return nil, fmt.Errorf("failed to unmarshal nurikabe save: %w", err)37 }38 if s.Width <= 0 || s.Height <= 0 {39 return nil, fmt.Errorf("invalid save dimensions: %dx%d", s.Width, s.Height)40 }4142 clues, err := parseClues(s.Clues, s.Width, s.Height)43 if err != nil {44 return nil, fmt.Errorf("invalid clue data: %w", err)45 }46 if err := validateClues(clues, s.Width, s.Height); err != nil {47 return nil, err48 }4950 marks, err := parseGrid(s.Marks, s.Width, s.Height)51 if err != nil {52 return nil, fmt.Errorf("invalid mark data: %w", err)53 }5455 for y := range s.Height {56 for x := range s.Width {57 if clues[y][x] > 0 {58 marks[y][x] = islandCell59 }60 }61 }6263 initial := newGrid(s.Width, s.Height, unknownCell)64 for y := range s.Height {65 for x := range s.Width {66 if clues[y][x] > 0 {67 initial[y][x] = islandCell68 }69 }70 }7172 m := &Model{73 width: s.Width,74 height: s.Height,75 clues: clues,76 marks: marks,77 initialMarks: initial,78 cursor: game.Cursor{X: 0, Y: 0},79 keys: DefaultKeyMap,80 modeTitle: s.ModeTitle,81 dragTarget: unknownCell,82 }83 m.recomputeDerivedState()84 return m, nil85}