diff --git a/puz/ipuz.go b/puz/ipuz.go index e05e989..a1d540b 100644 --- a/puz/ipuz.go +++ b/puz/ipuz.go @@ -63,6 +63,8 @@ func ParseIPuz(file []byte) (*Puzzle, error) { puzzle := new(Puzzle) + puzzle.RebusCells = make(map[int]string) + puzzle.Title = parsed.Title puzzle.Author = parsed.Author puzzle.Copyright = parsed.Copyright @@ -95,12 +97,13 @@ func ParseIPuz(file []byte) (*Puzzle, error) { puzzle.State = state.String() solution := strings.Builder{} - for _, row := range parsed.Solution { - for _, cell := range row { + for y, row := range parsed.Solution { + for x, cell := range row { if cell == "#" { solution.WriteRune('.') } else if len(cell) > 1 { solution.WriteByte(cell[0]) + puzzle.RebusCells[y*puzzle.Width+x] = cell puzzle.HasRebus = true } else if len(cell) == 1 { solution.WriteString(cell) diff --git a/puz/puz.go b/puz/puz.go index 09b213e..e2c4561 100644 --- a/puz/puz.go +++ b/puz/puz.go @@ -7,6 +7,8 @@ import ( "errors" "io" "math" + "regexp" + "strconv" "strings" "golang.org/x/text/encoding/charmap" @@ -123,6 +125,8 @@ func ParsePuz(file []byte) (*Puzzle, error) { puzzle := new(Puzzle) + puzzle.RebusCells = make(map[int]string) + _, err = r.Seek(10, io.SeekCurrent) if err != nil { return nil, err @@ -217,6 +221,8 @@ func ParsePuz(file []byte) (*Puzzle, error) { return nil, err } + extraBlocks := make(map[string]*ExtraBlock) + for { extra, err := readExtraBlock(buf) if errors.Is(err, io.EOF) { @@ -224,8 +230,30 @@ func ParsePuz(file []byte) (*Puzzle, error) { } else if err != nil { return nil, err } - if extra.Name == "RTBL" { - puzzle.HasRebus = true + extraBlocks[extra.Name] = extra + } + + grbs, grbsOk := extraBlocks["GRBS"] + trbl, trblOk := extraBlocks["RTBL"] + if grbsOk && trblOk { + puzzle.HasRebus = true + rebusCellMap := make(map[int][]int) + for i, b := range grbs.Data { + if b > 0 { + rebusCellMap[int(b)-1] = append(rebusCellMap[int(b)-1], i) + } + } + + rebusData := regexp.MustCompile(`\s*(\d+):(\w+);\s*`).FindAllStringSubmatch(string(trbl.Data), -1) + for _, rebus := range rebusData { + cell, err := strconv.Atoi(rebus[1]) + if err != nil { + continue + } + + for _, c := range rebusCellMap[cell] { + puzzle.RebusCells[c] = rebus[2] + } } } diff --git a/puz/shared.go b/puz/shared.go index 882f48c..dbb739c 100644 --- a/puz/shared.go +++ b/puz/shared.go @@ -38,6 +38,8 @@ type Puzzle struct { Cells [][2]*Clue HasRebus bool + + RebusCells map[int]string } func LoadPuzzle(r io.Reader) (*Puzzle, error) {