diff options
Diffstat (limited to 'internal/behavior/desc.go')
| -rw-r--r-- | internal/behavior/desc.go | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/internal/behavior/desc.go b/internal/behavior/desc.go index f6dbaf3..744b97e 100644 --- a/internal/behavior/desc.go +++ b/internal/behavior/desc.go @@ -1,8 +1,77 @@ package behavior +import ( + "fmt" + + "gopkg.in/yaml.v3" +) + +// DescVariant is one alternative description, optionally gated by a condition. type DescVariant struct { Text string `yaml:"text"` Condition *Condition `yaml:"condition,omitempty"` } +// DescList is an ordered list of description variants. The first variant whose +// condition matches is shown. +// +// Content may author the common single, unconditional description two ways: +// as a bare scalar (`description: "A dark room."`) or as a list of variants +// (`description: [{text: "A dark room."}]`). MarshalYAML collapses a single +// unconditional variant back to the scalar form so machine-written room files +// stay close to what a human would type. type DescList []DescVariant + +func (d *DescList) UnmarshalYAML(value *yaml.Node) error { + switch value.Kind { + case yaml.ScalarNode: + var text string + if err := value.Decode(&text); err != nil { + return err + } + if text == "" { + *d = nil + return nil + } + *d = DescList{{Text: text}} + return nil + case yaml.SequenceNode: + out := make(DescList, 0, len(value.Content)) + for _, item := range value.Content { + // Accept a bare string element as shorthand for a variant. + if item.Kind == yaml.ScalarNode { + var text string + if err := item.Decode(&text); err != nil { + return err + } + out = append(out, DescVariant{Text: text}) + continue + } + var variant DescVariant + if err := item.Decode(&variant); err != nil { + return err + } + out = append(out, variant) + } + *d = out + return nil + case yaml.AliasNode: + return d.UnmarshalYAML(value.Alias) + case 0: + // An omitted/zero node leaves the list empty. + *d = nil + return nil + default: + return fmt.Errorf("description must be a string or a list of variants") + } +} + +func (d DescList) MarshalYAML() (any, error) { + if len(d) == 0 { + return []DescVariant{}, nil + } + if len(d) == 1 && d[0].Condition == nil { + return d[0].Text, nil + } + return []DescVariant(d), nil +} |
