clone

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

main
puzzletea / games / takuzuplus / export.go
export.go 2.4K
1package takuzuplus23import (4 "encoding/json"5 "fmt"6 "strings"78 "github.com/FelineStateMachine/puzzletea/game"9)1011type Save struct {12 Size int `json:"size"`13 State string `json:"state"`14 Provided string `json:"provided"`15 ModeTitle string `json:"mode_title"`16 HorizontalRelations string `json:"horizontal_relations"`17 VerticalRelations string `json:"vertical_relations"`18}1920func (m Model) GetSave() ([]byte, error) {21 save := Save{22 Size: m.size,23 State: m.grid.String(),24 Provided: serializeProvided(m.provided),25 ModeTitle: m.modeTitle,26 HorizontalRelations: serializeRuneRows(m.relations.horizontal),27 VerticalRelations: serializeRuneRows(m.relations.vertical),28 }29 data, err := json.Marshal(save)30 if err != nil {31 return nil, fmt.Errorf("failed to marshal takuzu+ save: %w", err)32 }33 return data, nil34}3536func ImportModel(data []byte) (*Model, error) {37 var s Save38 if err := json.Unmarshal(data, &s); err != nil {39 return nil, fmt.Errorf("failed to unmarshal takuzu+ save: %w", err)40 }41 if s.Size <= 0 {42 return nil, fmt.Errorf("invalid grid size in save: %d", s.Size)43 }4445 g := newGridFromState(s.State)46 provided := deserializeProvided(s.Provided, s.Size)47 rels := relations{48 horizontal: deserializeRuneRows(s.HorizontalRelations, s.Size, max(s.Size-1, 0)),49 vertical: deserializeRuneRows(s.VerticalRelations, max(s.Size-1, 0), s.Size),50 }5152 initial := g.clone()53 for y := range s.Size {54 for x := range s.Size {55 if !provided[y][x] {56 initial[y][x] = emptyCell57 }58 }59 }6061 m := &Model{62 size: s.Size,63 grid: g,64 initialGrid: initial,65 provided: provided,66 relations: rels,67 cursor: game.Cursor{X: 0, Y: 0},68 keys: DefaultKeyMap,69 modeTitle: s.ModeTitle,70 }71 m.solved = m.checkSolved()72 return m, nil73}7475func serializeProvided(p [][]bool) string {76 var b strings.Builder77 for y, row := range p {78 for _, v := range row {79 if v {80 b.WriteByte('#')81 } else {82 b.WriteByte('.')83 }84 }85 if y < len(p)-1 {86 b.WriteByte('\n')87 }88 }89 return b.String()90}9192func deserializeProvided(s string, size int) [][]bool {93 rows := strings.Split(s, "\n")94 p := make([][]bool, size)95 for y := range size {96 p[y] = make([]bool, size)97 if y >= len(rows) {98 continue99 }100 for x := range size {101 if x < len(rows[y]) && rows[y][x] == '#' {102 p[y][x] = true103 }104 }105 }106 return p107}