horsegen: generate skill groups

This commit is contained in:
2026-01-09 14:24:31 -05:00
parent 024742c053
commit 7d8c6ae82e
6 changed files with 1207 additions and 17 deletions

View File

@@ -1,15 +1,17 @@
package main
import (
_ "embed"
"embed"
"fmt"
"io"
"regexp"
"strings"
"text/template"
"unicode"
)
//go:embed character.kk.template
var characterKK string
//go:embed character.kk.template skill.kk.template
var templates embed.FS
// LoadTemplates sets up templates to render game data to source code.
func LoadTemplates() (*template.Template, error) {
@@ -17,15 +19,11 @@ func LoadTemplates() (*template.Template, error) {
t.Funcs(template.FuncMap{
"kkenum": kkenum,
})
t, err := t.Parse(characterKK)
if err != nil {
return nil, fmt.Errorf("parsing characterKK: %w", err)
}
return t, nil
return t.ParseFS(templates, "*")
}
// ExecCharacterKK renders the Koka character module to w.
func ExecCharacterKK(t *template.Template, w io.Writer, c []Character, pairs, trios []AffinityRelation) error {
func ExecCharacterKK(t *template.Template, w io.Writer, c []NamedID[Character], pairs, trios []AffinityRelation) error {
if len(pairs) != len(c)*len(c) {
return fmt.Errorf("there are %d pairs but there must be %d for %d characters", len(pairs), len(c)*len(c), len(c))
}
@@ -52,7 +50,7 @@ func ExecCharacterKK(t *template.Template, w io.Writer, c []Character, pairs, tr
}
data := struct {
Characters []Character
Characters []NamedID[Character]
Pairs []AffinityRelation
Trios []AffinityRelation
PairMaps map[int]map[int]int
@@ -63,8 +61,56 @@ func ExecCharacterKK(t *template.Template, w io.Writer, c []Character, pairs, tr
return t.ExecuteTemplate(w, "koka-character", &data)
}
func ExecSkillKK(t *template.Template, w io.Writer, g []NamedID[SkillGroup]) error {
data := struct {
Groups []NamedID[SkillGroup]
}{g}
return t.ExecuteTemplate(w, "koka-skill", &data)
}
const replaceDash = " ,!?/+();#○◎☆♡'&=♪∀゚∴"
var (
kkReplace = func() *strings.Replacer {
r := []string{
"Triple 7s", "Triple-Sevens", // hard to replace with the right thing automatically
"1,500,000 CC", "Million-CC",
"1st", "First",
".", "",
"'s", "s",
"ó", "o",
"∞", "Infinity",
}
for _, c := range replaceDash {
r = append(r, string(c), "-")
}
return strings.NewReplacer(r...)
}()
kkMultidash = regexp.MustCompile(`-+`)
kkDashNonletter = regexp.MustCompile(`-[^A-Za-z]`)
)
func kkenum(name string) string {
name = strings.ReplaceAll(name, ".", "")
name = strings.ReplaceAll(name, " ", "-")
orig := name
name = kkReplace.Replace(name)
name = kkMultidash.ReplaceAllLiteralString(name, "-")
name = strings.Trim(name, "-")
if len(name) == 0 {
panic(fmt.Errorf("%q became empty as Koka enum variant", orig))
}
name = strings.ToUpper(name[:1]) + name[1:]
if !unicode.IsLetter(rune(name[0])) {
panic(fmt.Errorf("Koka enum variant %q (from %q) starts with a non-letter", name, orig))
}
for _, c := range name {
if c > 127 {
// Koka does not allow non-ASCII characters in source code.
// Don't proceed if we've missed one.
panic(fmt.Errorf("non-ASCII character %q (%[1]U) in Koka enum variant %q (from %q)", c, name, orig))
}
}
if kkDashNonletter.MatchString(name) {
panic(fmt.Errorf("non-letter character after a dash in Koka enum variant %q (from %q)", name, orig))
}
return name
}