Files
horse/horsegen/gen.go

129 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"embed"
"fmt"
"io"
"regexp"
"strings"
"text/template"
"unicode"
)
//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) {
t := template.New("root")
t.Funcs(template.FuncMap{
"kkenum": kkenum,
})
return t.ParseFS(templates, "*")
}
// ExecCharacterKK renders the Koka character module to w.
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))
}
if len(trios) != len(c)*len(c)*len(c) {
return fmt.Errorf("there are %d trios but there must be %d for %d characters", len(trios), len(c)*len(c)*len(c), len(c))
}
maxid := 0
pm := make(map[int]map[int]int, len(c))
tm := make(map[int]map[int]map[int]int, len(c))
for _, u := range c {
maxid = max(maxid, u.ID)
pm[u.ID] = make(map[int]int, len(c))
tm[u.ID] = make(map[int]map[int]int, len(c))
for _, v := range c {
tm[u.ID][v.ID] = make(map[int]int, len(c))
}
}
for _, p := range pairs {
pm[p.IDA][p.IDB] = p.Affinity
}
for _, t := range trios {
tm[t.IDA][t.IDB][t.IDC] = t.Affinity
}
data := struct {
Characters []NamedID[Character]
Pairs []AffinityRelation
Trios []AffinityRelation
PairMaps map[int]map[int]int
TrioMaps map[int]map[int]map[int]int
Count int
MaxID int
}{c, pairs, trios, pm, tm, len(c), maxid}
return t.ExecuteTemplate(w, "koka-character", &data)
}
func ExecSkillKK(t *template.Template, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
data := struct {
Groups []NamedID[SkillGroup]
Skills []Skill
}{g, s}
return t.ExecuteTemplate(w, "koka-skill", &data)
}
func ExecSkillGroupKK(t *template.Template, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
data := struct {
Groups []NamedID[SkillGroup]
Skills []Skill
}{g, s}
return t.ExecuteTemplate(w, "koka-skill-group", &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", "One-Million-CC",
"15,000,000 CC", "Fifteen-Million-CC",
"1st", "First",
".", "",
"'s", "s",
"ó", "o",
"∞", "Infinity",
"×", "x",
"◎", "Lv2",
}
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 {
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
}