Compare commits
30 Commits
b22b77c535
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c00d3d0186 | |||
| a534975601 | |||
| b55e1bc200 | |||
| c58dbd19b0 | |||
| 2fcd608102 | |||
| 546f2db327 | |||
| 856c94723f | |||
| 2393bf2fa5 | |||
| bf06de0f5e | |||
| f3f070ca2b | |||
| 34edcf97a7 | |||
| 9dd18ed972 | |||
| 332cf3f13a | |||
| c5a1cdea5f | |||
| 542d4198e7 | |||
| 98afe7384a | |||
| e890108591 | |||
| 0126101b1b | |||
| 5bf2588d41 | |||
| a5f84754ea | |||
| 4bfb06b682 | |||
| 72b8bc9c6c | |||
| 1ae654c266 | |||
| 74ee76c5da | |||
| 36d27f1642 | |||
| 9469c2c7a2 | |||
| a8921e9cf6 | |||
| f9ad769d9f | |||
| ec2efee5d5 | |||
| d147d71519 |
1
cmd/horsebot/.gitignore
vendored
Normal file
1
cmd/horsebot/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
token
|
||||||
10
cmd/horsebot/README.md
Normal file
10
cmd/horsebot/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# horsebot
|
||||||
|
|
||||||
|
Discord bot serving horse game data.
|
||||||
|
|
||||||
|
Production instance is named Zenno Rob Roy, because she has read all about Umamusume and is always happy to share her knowledge and give recommendations.
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
The bot always uses the Gateway API.
|
||||||
|
If the `-http` argument is provided, it will also use the HTTP API, and `-key` must also be provided.
|
||||||
56
cmd/horsebot/autocomplete/autocomplete.go
Normal file
56
cmd/horsebot/autocomplete/autocomplete.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package autocomplete
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"cmp"
|
||||||
|
"slices"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/junegunn/fzf/src/algo"
|
||||||
|
"github.com/junegunn/fzf/src/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set is an autocomplete set.
|
||||||
|
type Set[V any] struct {
|
||||||
|
keys []util.Chars
|
||||||
|
vals []V
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add associates a value with a key in the autocomplete set.
|
||||||
|
// The behavior is undefined if the key already has a value.
|
||||||
|
func (s *Set[V]) Add(key string, val V) {
|
||||||
|
k := util.ToChars([]byte(key))
|
||||||
|
i, _ := slices.BinarySearchFunc(s.keys, k, func(a, b util.Chars) int {
|
||||||
|
return bytes.Compare(a.Bytes(), b.Bytes())
|
||||||
|
})
|
||||||
|
s.keys = slices.Insert(s.keys, i, k)
|
||||||
|
s.vals = slices.Insert(s.vals, i, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find appends to r all values in the set with keys that key matches.
|
||||||
|
func (s *Set[V]) Find(r []V, key string) []V {
|
||||||
|
initFzf()
|
||||||
|
var (
|
||||||
|
p = []rune(key)
|
||||||
|
|
||||||
|
got []V
|
||||||
|
t []algo.Result
|
||||||
|
slab util.Slab
|
||||||
|
)
|
||||||
|
for i := range s.keys {
|
||||||
|
res, _ := algo.FuzzyMatchV2(false, true, true, &s.keys[i], p, false, &slab)
|
||||||
|
if res.Score <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
j, _ := slices.BinarySearchFunc(t, res, func(a, b algo.Result) int { return -cmp.Compare(a.Score, b.Score) })
|
||||||
|
// Insert after all other matches with the same score for stability.
|
||||||
|
for j < len(t) && t[j].Score == res.Score {
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
t = slices.Insert(t, j, res)
|
||||||
|
got = slices.Insert(got, j, s.vals[i])
|
||||||
|
}
|
||||||
|
return append(r, got...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var initFzf = sync.OnceFunc(func() { algo.Init("default") })
|
||||||
70
cmd/horsebot/autocomplete/autocomplete_test.go
Normal file
70
cmd/horsebot/autocomplete/autocomplete_test.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package autocomplete_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/cmd/horsebot/autocomplete"
|
||||||
|
)
|
||||||
|
|
||||||
|
func these(s ...string) []string { return s }
|
||||||
|
|
||||||
|
func TestAutocomplete(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
add []string
|
||||||
|
search string
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
add: nil,
|
||||||
|
search: "",
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exact",
|
||||||
|
add: these("bocchi"),
|
||||||
|
search: "bocchi",
|
||||||
|
want: these("bocchi"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "extra",
|
||||||
|
add: these("bocchi", "ryo", "nijika", "kita"),
|
||||||
|
search: "bocchi",
|
||||||
|
want: these("bocchi"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "short",
|
||||||
|
add: these("bocchi", "ryo", "nijika", "kita"),
|
||||||
|
search: "o",
|
||||||
|
want: these("bocchi", "ryo"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unrelated",
|
||||||
|
add: these("bocchi", "ryo", "nijika", "kita"),
|
||||||
|
search: "x",
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map",
|
||||||
|
add: these("Corazón ☆ Ardiente"),
|
||||||
|
search: "corazo",
|
||||||
|
want: these("Corazón ☆ Ardiente"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
var set autocomplete.Set[string]
|
||||||
|
for _, s := range c.add {
|
||||||
|
set.Add(s, s)
|
||||||
|
}
|
||||||
|
got := set.Find(nil, c.search)
|
||||||
|
slices.Sort(c.want)
|
||||||
|
slices.Sort(got)
|
||||||
|
if !slices.Equal(c.want, got) {
|
||||||
|
t.Errorf("wrong results: want %q, got %q", c.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
55
cmd/horsebot/log.go
Normal file
55
cmd/horsebot/log.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/disgoorg/disgo/discord"
|
||||||
|
"github.com/disgoorg/disgo/handler"
|
||||||
|
)
|
||||||
|
|
||||||
|
func logMiddleware(next handler.Handler) handler.Handler {
|
||||||
|
return func(e *handler.InteractionEvent) error {
|
||||||
|
var msg string
|
||||||
|
attrs := make([]slog.Attr, 0, 8)
|
||||||
|
attrs = append(attrs,
|
||||||
|
slog.Uint64("interaction", uint64(e.Interaction.ID())),
|
||||||
|
slog.Uint64("user", uint64(e.Interaction.User().ID)),
|
||||||
|
)
|
||||||
|
if guild := e.Interaction.GuildID(); guild != nil {
|
||||||
|
attrs = append(attrs, slog.String("guild", guild.String()))
|
||||||
|
}
|
||||||
|
switch i := e.Interaction.(type) {
|
||||||
|
case discord.ApplicationCommandInteraction:
|
||||||
|
msg = "command"
|
||||||
|
attrs = append(attrs,
|
||||||
|
slog.String("name", i.Data.CommandName()),
|
||||||
|
slog.Int("type", int(i.Data.Type())),
|
||||||
|
)
|
||||||
|
switch data := i.Data.(type) {
|
||||||
|
case discord.SlashCommandInteractionData:
|
||||||
|
attrs = append(attrs, slog.String("path", data.CommandPath()))
|
||||||
|
}
|
||||||
|
|
||||||
|
case discord.AutocompleteInteraction:
|
||||||
|
msg = "autocomplete"
|
||||||
|
attrs = append(attrs,
|
||||||
|
slog.String("name", i.Data.CommandName),
|
||||||
|
slog.String("path", i.Data.CommandPath()),
|
||||||
|
slog.String("focus", i.Data.Focused().Name),
|
||||||
|
)
|
||||||
|
|
||||||
|
case discord.ComponentInteraction:
|
||||||
|
msg = "component"
|
||||||
|
attrs = append(attrs,
|
||||||
|
slog.Int("type", int(i.Data.Type())),
|
||||||
|
slog.String("custom", i.Data.CustomID()),
|
||||||
|
)
|
||||||
|
|
||||||
|
default:
|
||||||
|
slog.WarnContext(e.Ctx, "unknown interaction", slog.Any("event", e))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
slog.LogAttrs(e.Ctx, slog.LevelInfo, msg, attrs...)
|
||||||
|
return next(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
183
cmd/horsebot/main.go
Normal file
183
cmd/horsebot/main.go
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/disgoorg/disgo"
|
||||||
|
"github.com/disgoorg/disgo/bot"
|
||||||
|
"github.com/disgoorg/disgo/discord"
|
||||||
|
"github.com/disgoorg/disgo/handler"
|
||||||
|
"github.com/disgoorg/disgo/handler/middleware"
|
||||||
|
"github.com/disgoorg/disgo/httpserver"
|
||||||
|
"github.com/disgoorg/disgo/rest"
|
||||||
|
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/horse"
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/horse/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
tokenFile string
|
||||||
|
// http api options
|
||||||
|
addr string
|
||||||
|
route string
|
||||||
|
pubkey string
|
||||||
|
// logging options
|
||||||
|
level slog.Level
|
||||||
|
textfmt string
|
||||||
|
)
|
||||||
|
flag.StringVar(&tokenFile, "token", "", "`file` containing the Discord bot token")
|
||||||
|
flag.StringVar(&addr, "http", "", "`address` to bind HTTP API server")
|
||||||
|
flag.StringVar(&route, "route", "/interactions/callback", "`path` to serve HTTP API calls")
|
||||||
|
flag.StringVar(&pubkey, "key", "", "Discord public key")
|
||||||
|
flag.TextVar(&level, "log", slog.LevelInfo, "slog logging `level`")
|
||||||
|
flag.StringVar(&textfmt, "log-format", "text", "slog logging `format`, text or json")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var lh slog.Handler
|
||||||
|
switch textfmt {
|
||||||
|
case "text":
|
||||||
|
lh = slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level})
|
||||||
|
case "json":
|
||||||
|
lh = slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: level})
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "invalid log format %q, must be text or json", textfmt)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
slog.SetDefault(slog.New(lh))
|
||||||
|
|
||||||
|
token, err := os.ReadFile(tokenFile)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("reading token", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
token = bytes.TrimSuffix(token, []byte{'\n'})
|
||||||
|
|
||||||
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||||
|
|
||||||
|
r := handler.New()
|
||||||
|
r.DefaultContext(func() context.Context { return ctx })
|
||||||
|
r.Use(middleware.Go)
|
||||||
|
r.Use(logMiddleware)
|
||||||
|
r.Route("/skill", func(r handler.Router) {
|
||||||
|
r.SlashCommand("/", skillHandler)
|
||||||
|
r.Autocomplete("/", skillAutocomplete)
|
||||||
|
r.ButtonComponent("/{id}", skillButton)
|
||||||
|
})
|
||||||
|
|
||||||
|
opts := []bot.ConfigOpt{bot.WithDefaultGateway(), bot.WithEventListeners(r)}
|
||||||
|
if addr != "" {
|
||||||
|
if pubkey == "" {
|
||||||
|
slog.Error("Discord public key must be provided when using HTTP API")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
opts = append(opts, bot.WithHTTPServerConfigOpts(pubkey,
|
||||||
|
httpserver.WithAddress(addr),
|
||||||
|
httpserver.WithURL(route),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Info("connect", slog.String("disgo", disgo.Version))
|
||||||
|
client, err := disgo.New(string(token), opts...)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("building bot", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := handler.SyncCommands(client, commands, nil, rest.WithCtx(ctx)); err != nil {
|
||||||
|
slog.Error("syncing commands", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if addr != "" {
|
||||||
|
slog.Info("start HTTP server", slog.String("address", addr), slog.String("route", route))
|
||||||
|
if err := client.OpenHTTPServer(); err != nil {
|
||||||
|
slog.Error("starting HTTP server", slog.Any("err", err))
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slog.Info("start gateway")
|
||||||
|
if err := client.OpenGateway(ctx); err != nil {
|
||||||
|
slog.Error("starting gateway", slog.Any("err", err))
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
slog.Info("ready")
|
||||||
|
<-ctx.Done()
|
||||||
|
stop()
|
||||||
|
|
||||||
|
ctx, stop = context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer stop()
|
||||||
|
client.Close(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
var commands = []discord.ApplicationCommandCreate{
|
||||||
|
discord.SlashCommandCreate{
|
||||||
|
Name: "skill",
|
||||||
|
Description: "Umamusume skill data",
|
||||||
|
Options: []discord.ApplicationCommandOption{
|
||||||
|
discord.ApplicationCommandOptionString{
|
||||||
|
Name: "query",
|
||||||
|
Description: "Skill name or ID",
|
||||||
|
Required: true,
|
||||||
|
Autocomplete: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func skillHandler(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error {
|
||||||
|
q := data.String("query")
|
||||||
|
id, err := strconv.ParseInt(q, 10, 32)
|
||||||
|
if err == nil {
|
||||||
|
// note inverted condition; this is when we have an id
|
||||||
|
id = int64(global.AllSkills[horse.SkillID(id)].ID)
|
||||||
|
}
|
||||||
|
if id == 0 {
|
||||||
|
// Either we weren't given a number or the number doesn't match any skill ID.
|
||||||
|
v := global.SkillNameToID[q]
|
||||||
|
if v == 0 {
|
||||||
|
// No such skill.
|
||||||
|
m := discord.MessageCreate{
|
||||||
|
Content: "No such skill.",
|
||||||
|
Flags: discord.MessageFlagEphemeral,
|
||||||
|
}
|
||||||
|
return e.CreateMessage(m)
|
||||||
|
}
|
||||||
|
id = int64(v)
|
||||||
|
}
|
||||||
|
// TODO(zeph): search conditions and effects, give a list
|
||||||
|
m := discord.MessageCreate{
|
||||||
|
Components: []discord.LayoutComponent{RenderSkill(horse.SkillID(id), global.AllSkills, global.SkillGroups)},
|
||||||
|
Flags: discord.MessageFlagIsComponentsV2,
|
||||||
|
}
|
||||||
|
return e.CreateMessage(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func skillAutocomplete(e *handler.AutocompleteEvent) error {
|
||||||
|
q := e.Data.String("query")
|
||||||
|
opts := skillGlobalAuto().Find(nil, q)
|
||||||
|
return e.AutocompleteResult(opts[:min(len(opts), 25)])
|
||||||
|
}
|
||||||
|
|
||||||
|
func skillButton(data discord.ButtonInteractionData, e *handler.ComponentEvent) error {
|
||||||
|
id, err := strconv.ParseInt(e.Vars["id"], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
m := discord.MessageCreate{
|
||||||
|
Content: "That button produced an invalid skill ID. That's not supposed to happen.",
|
||||||
|
Flags: discord.MessageFlagEphemeral,
|
||||||
|
}
|
||||||
|
return e.CreateMessage(m)
|
||||||
|
}
|
||||||
|
m := discord.MessageUpdate{
|
||||||
|
Components: &[]discord.LayoutComponent{RenderSkill(horse.SkillID(id), global.AllSkills, global.SkillGroups)},
|
||||||
|
}
|
||||||
|
return e.UpdateMessage(m)
|
||||||
|
}
|
||||||
148
cmd/horsebot/skill.go
Normal file
148
cmd/horsebot/skill.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/disgoorg/disgo/discord"
|
||||||
|
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/cmd/horsebot/autocomplete"
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/horse"
|
||||||
|
"git.sunturtle.xyz/zephyr/horse/horse/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RenderSkill(id horse.SkillID, all map[horse.SkillID]horse.Skill, groups map[int32][4]horse.SkillID) discord.ContainerComponent {
|
||||||
|
s, ok := all[id]
|
||||||
|
if !ok {
|
||||||
|
return discord.NewContainer(discord.NewTextDisplayf("invalid skill ID %v made it to RenderSkill", id))
|
||||||
|
}
|
||||||
|
|
||||||
|
thumburl := fmt.Sprintf("https://gametora.com/images/umamusume/skill_icons/utx_ico_skill_%d.png", s.IconID)
|
||||||
|
top := "## " + s.Name
|
||||||
|
if s.UniqueOwner != "" {
|
||||||
|
top += "\n-# " + s.UniqueOwner
|
||||||
|
}
|
||||||
|
r := discord.NewContainer(
|
||||||
|
discord.NewSection(
|
||||||
|
discord.NewTextDisplay(top),
|
||||||
|
discord.NewTextDisplay(s.Description),
|
||||||
|
).WithAccessory(discord.NewThumbnail(thumburl)),
|
||||||
|
)
|
||||||
|
var skilltype string
|
||||||
|
switch {
|
||||||
|
case s.Rarity == 3, s.Rarity == 4, s.Rarity == 5:
|
||||||
|
// unique of various star levels
|
||||||
|
r.AccentColor = 0xaca4d4
|
||||||
|
skilltype = "Unique Skill"
|
||||||
|
case s.UniqueOwner != "":
|
||||||
|
r.AccentColor = 0xcccccc
|
||||||
|
skilltype = "Inherited Unique"
|
||||||
|
case s.Rarity == 2:
|
||||||
|
// rare (gold)
|
||||||
|
r.AccentColor = 0xd7c25b
|
||||||
|
skilltype = "Rare Skill"
|
||||||
|
case s.GroupRate == -1:
|
||||||
|
// negative (purple) skill
|
||||||
|
r.AccentColor = 0x9151d4
|
||||||
|
skilltype = "Negative Skill"
|
||||||
|
case !s.WitCheck:
|
||||||
|
// should be passive (green)
|
||||||
|
r.AccentColor = 0x66ae1c
|
||||||
|
skilltype = "Passive Skill"
|
||||||
|
case isDebuff(s):
|
||||||
|
// debuff (red)
|
||||||
|
r.AccentColor = 0xe34747
|
||||||
|
skilltype = "Debuff Skill"
|
||||||
|
case s.Rarity == 1:
|
||||||
|
// common (white)
|
||||||
|
r.AccentColor = 0xcccccc
|
||||||
|
skilltype = "Common Skill"
|
||||||
|
}
|
||||||
|
r.Components = append(r.Components, discord.NewSmallSeparator())
|
||||||
|
text := make([]string, 0, 3)
|
||||||
|
abils := make([]string, 0, 3)
|
||||||
|
for _, act := range s.Activations {
|
||||||
|
text, abils = text[:0], abils[:0]
|
||||||
|
if act.Precondition != "" {
|
||||||
|
text = append(text, "Precondition: "+formatCondition(act.Precondition))
|
||||||
|
}
|
||||||
|
text = append(text, "Condition: "+formatCondition(act.Condition))
|
||||||
|
var t string
|
||||||
|
switch {
|
||||||
|
case act.Duration < 0:
|
||||||
|
// passive; do nothing
|
||||||
|
case act.Duration == 0:
|
||||||
|
t = "Instantaneous "
|
||||||
|
case act.Duration >= 500e4:
|
||||||
|
t = "Permanent "
|
||||||
|
default:
|
||||||
|
t = "For " + act.Duration.String() + "s, "
|
||||||
|
}
|
||||||
|
for _, a := range act.Abilities {
|
||||||
|
abils = append(abils, a.String())
|
||||||
|
}
|
||||||
|
t += strings.Join(abils, ", ")
|
||||||
|
if act.Cooldown > 0 && act.Cooldown < 500e4 {
|
||||||
|
t += " on " + act.Cooldown.String() + "s cooldown"
|
||||||
|
}
|
||||||
|
text = append(text, t)
|
||||||
|
r.Components = append(r.Components, discord.NewTextDisplay(strings.Join(text, "\n")))
|
||||||
|
}
|
||||||
|
|
||||||
|
l := discord.NewTextDisplayf("%s ・ SP cost %d ・ Grade value %d ・ [Conditions on GameTora](https://gametora.com/umamusume/skill-condition-viewer?skill=%d)", skilltype, s.SPCost, s.GradeValue, s.ID)
|
||||||
|
r.Components = append(r.Components, discord.NewSmallSeparator(), l)
|
||||||
|
rel := make([]horse.Skill, 0, 4)
|
||||||
|
for _, id := range groups[s.Group] {
|
||||||
|
if id != 0 {
|
||||||
|
rel = append(rel, all[id])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(rel) > 1 {
|
||||||
|
buttons := make([]discord.InteractiveComponent, 0, 4)
|
||||||
|
for _, rs := range rel {
|
||||||
|
b := discord.NewSecondaryButton(rs.Name, fmt.Sprintf("/skill/%d", rs.ID))
|
||||||
|
if rs.ID == id {
|
||||||
|
b = b.AsDisabled()
|
||||||
|
}
|
||||||
|
buttons = append(buttons, b)
|
||||||
|
}
|
||||||
|
r.Components = append(r.Components, discord.NewActionRow(buttons...))
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatCondition(s string) string {
|
||||||
|
s = strings.ReplaceAll(s, "&", " & ")
|
||||||
|
if strings.ContainsRune(s, '@') {
|
||||||
|
return "```\n" + strings.ReplaceAll(s, "@", "\n@\n") + "```"
|
||||||
|
}
|
||||||
|
return "`" + s + "`"
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDebuff(s horse.Skill) bool {
|
||||||
|
for _, act := range s.Activations {
|
||||||
|
for _, a := range act.Abilities {
|
||||||
|
if a.Value < 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var skillGlobalAuto = sync.OnceValue(func() *autocomplete.Set[discord.AutocompleteChoice] {
|
||||||
|
var set autocomplete.Set[discord.AutocompleteChoice]
|
||||||
|
for _, id := range global.OrderedSkills {
|
||||||
|
s := global.AllSkills[id]
|
||||||
|
set.Add(s.Name, discord.AutocompleteChoiceString{Name: s.Name, Value: s.Name})
|
||||||
|
if s.UniqueOwner != "" {
|
||||||
|
if s.Rarity >= 3 {
|
||||||
|
set.Add(s.UniqueOwner, discord.AutocompleteChoiceString{Name: "Unique: " + s.UniqueOwner, Value: s.Name})
|
||||||
|
} else {
|
||||||
|
set.Add(s.UniqueOwner, discord.AutocompleteChoiceString{Name: "Inherited unique: " + s.UniqueOwner, Value: s.Name})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &set
|
||||||
|
})
|
||||||
1903
doc/2026-01-22-global.diff
Normal file
1903
doc/2026-01-22-global.diff
Normal file
File diff suppressed because it is too large
Load Diff
123780
doc/2026-01-22-global.sql
Normal file
123780
doc/2026-01-22-global.sql
Normal file
File diff suppressed because it is too large
Load Diff
1574
doc/2026-01-29-global.diff
Normal file
1574
doc/2026-01-29-global.diff
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ This file is my notes from exploring the database.
|
|||||||
- 47 is skill names, 48 is skill descriptions
|
- 47 is skill names, 48 is skill descriptions
|
||||||
- 75 is support card names incl. variant, 76 is support card variant, 77 is support card character
|
- 75 is support card names incl. variant, 76 is support card variant, 77 is support card character
|
||||||
- 147 is spark names, 172 is spark descriptions
|
- 147 is spark names, 172 is spark descriptions
|
||||||
- 33 is race names by race id, 28 is race names by race instance id, 31 is race courses
|
- 33 is race names by race id, 28 is race names by race instance id, 31 is race courses, 111 is saddle names
|
||||||
- 65 is player titles, 66 is title descriptions - ties with honor_data?
|
- 65 is player titles, 66 is title descriptions - ties with honor_data?
|
||||||
|
|
||||||
# succession factor (sparks)
|
# succession factor (sparks)
|
||||||
@@ -128,8 +128,8 @@ race sparks with skills always give +1, skill sparks always give +1-5, unique sp
|
|||||||
|
|
||||||
- single_mode_skill_need_point is base number of skill points to buy each skill
|
- single_mode_skill_need_point is base number of skill points to buy each skill
|
||||||
- support card skill hints are defined in single_mode_hint_gain
|
- support card skill hints are defined in single_mode_hint_gain
|
||||||
- skill_set is NOT trainee skills, seems to be npcs
|
- skill_set includes trainee unique starting skills, among many other things
|
||||||
- available_skill_set has trainee starting skills
|
- available_skill_set has trainee starting skills other than their uniques
|
||||||
|
|
||||||
skill categories:
|
skill categories:
|
||||||
- 0 passive
|
- 0 passive
|
||||||
@@ -193,6 +193,22 @@ seems to be activate_lot = 1 means wit check, 0 means guaranteed
|
|||||||
|
|
||||||
single_mode_wins_saddle defines titles (classic triple crown, tenno sweep, &c.) using win_saddle_type = 0
|
single_mode_wins_saddle defines titles (classic triple crown, tenno sweep, &c.) using win_saddle_type = 0
|
||||||
|
|
||||||
|
race_instance is a combination of race, npc group, race date (month*100 + day), and time of day.
|
||||||
|
it isn't actually anything i care about.
|
||||||
|
|
||||||
|
which is to say, what i do care about is mapping races to each turn they're offered, and having a "race instance" enum like Hopeful-Stakes-Junior, Yasuda-Kinen-Classic, &c.
|
||||||
|
|
||||||
|
single_mode_program defines the race instances available for each turn, but the year is expressed a bit weirdly in the race_permission column:
|
||||||
|
- 1 = junior year
|
||||||
|
- 2 = classic year
|
||||||
|
- 3 = classic and senior year
|
||||||
|
- 4 = senior year
|
||||||
|
- 5 = ura finale
|
||||||
|
|
||||||
|
grade_rate_id appears to be consistently 800 iff maiden race and 900 iff debut race, but the values particularly for g1s are all over the place.
|
||||||
|
recommend_class_id appears to be consistently 1 iff maiden race or debut race, 2 iff pre-op, 3 iff op; but other values are confusing.
|
||||||
|
so, it doesn't seem like there's a particular flag that identifies maiden races, despite the restrictions on when they appear in the ui.
|
||||||
|
|
||||||
# trainee definitions
|
# trainee definitions
|
||||||
|
|
||||||
- card_data has universal trainee stats: base skill set, stat growth bonuses ("talent"), default running style
|
- card_data has universal trainee stats: base skill set, stat growth bonuses ("talent"), default running style
|
||||||
@@ -201,6 +217,68 @@ single_mode_wins_saddle defines titles (classic triple crown, tenno sweep, &c.)
|
|||||||
- card_talent_hint_upgrade has costs to raise hint levels, but it's actually universal, only six rows
|
- card_talent_hint_upgrade has costs to raise hint levels, but it's actually universal, only six rows
|
||||||
- single_mode_route_race is career goals (not only races)
|
- single_mode_route_race is career goals (not only races)
|
||||||
|
|
||||||
# unrelated to everything
|
# update diffs
|
||||||
|
|
||||||
try doober with E long, all-seeing eyes, gold recovery, and lots of stamina running in g3 diamond stakes senior year late february
|
complete list of tables with inserts in both the 2026-01-15 update adding fine motion, manhattan cafe ssr, inari one sr and the 2026-01-22 update adding tamamo cross and main story 5:
|
||||||
|
|
||||||
|
- announce_character
|
||||||
|
- announce_data
|
||||||
|
- available_skill_set
|
||||||
|
- background_data
|
||||||
|
- banner_data
|
||||||
|
- campaign_chara_story_schedule
|
||||||
|
- campaign_data
|
||||||
|
- campaign_single_race_add_data
|
||||||
|
- campaign_single_race_add_reward
|
||||||
|
- card_data
|
||||||
|
- card_rarity_data
|
||||||
|
- card_talent_upgrade
|
||||||
|
- champions_news_chara_comment
|
||||||
|
- chara_category_motion
|
||||||
|
- character_system_lottery
|
||||||
|
- character_system_text
|
||||||
|
- chara_motion_set
|
||||||
|
- chara_story_data
|
||||||
|
- dress_data
|
||||||
|
- gacha_available
|
||||||
|
- gacha_data
|
||||||
|
- gacha_exchange
|
||||||
|
- gacha_top_bg
|
||||||
|
- home_story_trigger
|
||||||
|
- home_walk_group
|
||||||
|
- honor_data
|
||||||
|
- item_exchange
|
||||||
|
- item_place
|
||||||
|
- jukebox_chara_tag_data
|
||||||
|
- jukebox_comment
|
||||||
|
- jukebox_reaction_data
|
||||||
|
- mission_data
|
||||||
|
- nickname
|
||||||
|
- piece_data
|
||||||
|
- race
|
||||||
|
- race_bgm_cutin_extension_time
|
||||||
|
- race_instance
|
||||||
|
- race_jikkyo_base
|
||||||
|
- race_jikkyo_race
|
||||||
|
- race_jikkyo_trigger
|
||||||
|
- single_mode_chara_program
|
||||||
|
- single_mode_conclusion_set
|
||||||
|
- single_mode_event_production
|
||||||
|
- single_mode_hint_gain
|
||||||
|
- single_mode_npc
|
||||||
|
- single_mode_rival
|
||||||
|
- single_mode_route
|
||||||
|
- single_mode_route_race
|
||||||
|
- single_mode_scout_chara
|
||||||
|
- single_mode_skill_need_point
|
||||||
|
- single_mode_story_data
|
||||||
|
- single_mode_tag_card_pos
|
||||||
|
- skill_data
|
||||||
|
- skill_set
|
||||||
|
- succession_factor
|
||||||
|
- succession_factor_effect
|
||||||
|
- succession_relation_member
|
||||||
|
- support_card_data
|
||||||
|
- support_card_effect_table
|
||||||
|
- support_card_unique_effect
|
||||||
|
- text_data
|
||||||
|
|||||||
8
generate.sh
Executable file
8
generate.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
go run ./horsegen "$@"
|
||||||
|
go generate ./horse/...
|
||||||
|
go fmt ./...
|
||||||
|
go test ./...
|
||||||
14
go.mod
14
go.mod
@@ -1,20 +1,30 @@
|
|||||||
module git.sunturtle.xyz/zephyr/horse
|
module git.sunturtle.xyz/zephyr/horse
|
||||||
|
|
||||||
go 1.24.1
|
go 1.25.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/disgoorg/disgo v0.19.0-rc.15
|
||||||
|
github.com/junegunn/fzf v0.67.0
|
||||||
golang.org/x/sync v0.14.0
|
golang.org/x/sync v0.14.0
|
||||||
zombiezen.com/go/sqlite v1.4.2
|
zombiezen.com/go/sqlite v1.4.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/disgoorg/json/v2 v2.0.0 // indirect
|
||||||
|
github.com/disgoorg/omit v1.0.0 // indirect
|
||||||
|
github.com/disgoorg/snowflake/v2 v2.0.3 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/klauspost/compress v1.18.2 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
|
||||||
|
golang.org/x/crypto v0.46.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
golang.org/x/sys v0.39.0 // indirect
|
||||||
modernc.org/libc v1.65.7 // indirect
|
modernc.org/libc v1.65.7 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
|
|||||||
36
go.sum
36
go.sum
@@ -1,15 +1,41 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/disgoorg/disgo v0.19.0-rc.15 h1:x0NsV2gcbdjwuztsg2wYXw76p1Cpc8f6ByDrkPcfQtU=
|
||||||
|
github.com/disgoorg/disgo v0.19.0-rc.15/go.mod h1:14mgXzenkJqifkDmsEgU0zI1di6jNXodwX6L8geW33A=
|
||||||
|
github.com/disgoorg/json/v2 v2.0.0 h1:U16yy/ARK7/aEpzjjqK1b/KaqqGHozUdeVw/DViEzQI=
|
||||||
|
github.com/disgoorg/json/v2 v2.0.0/go.mod h1:jZTBC0nIE1WeetSEI3/Dka8g+qglb4FPVmp5I5HpEfI=
|
||||||
|
github.com/disgoorg/omit v1.0.0 h1:y0LkVUOyUHT8ZlnhIAeOZEA22UYykeysK8bLJ0SfT78=
|
||||||
|
github.com/disgoorg/omit v1.0.0/go.mod h1:RTmSARkf6PWT/UckwI0bV8XgWkWQoPppaT01rYKLcFQ=
|
||||||
|
github.com/disgoorg/snowflake/v2 v2.0.3 h1:3B+PpFjr7j4ad7oeJu4RlQ+nYOTadsKapJIzgvSI2Ro=
|
||||||
|
github.com/disgoorg/snowflake/v2 v2.0.3/go.mod h1:W6r7NUA7DwfZLwr00km6G4UnZ0zcoLBRufhkFWgAc4c=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/junegunn/fzf v0.67.0 h1:naiOdIkV5/ZCfHgKQIV/f5YDWowl95G6yyOQqW8FeSo=
|
||||||
|
github.com/junegunn/fzf v0.67.0/go.mod h1:xlXX2/rmsccKQUnr9QOXPDi5DyV9cM0UjKy/huScBeE=
|
||||||
|
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||||
|
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad h1:qIQkSlF5vAUHxEmTbaqt1hkJ/t6skqEGYiMag343ucI=
|
||||||
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||||
|
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||||
@@ -17,12 +43,14 @@ golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
|||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
|
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
|
||||||
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||||
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
||||||
|
|||||||
@@ -9,29 +9,53 @@ func _() {
|
|||||||
// Re-run the stringer command to generate them again.
|
// Re-run the stringer command to generate them again.
|
||||||
var x [1]struct{}
|
var x [1]struct{}
|
||||||
_ = x[ValueUsageDirect-1]
|
_ = x[ValueUsageDirect-1]
|
||||||
|
_ = x[ValueUsageSkillCount-2]
|
||||||
_ = x[ValueUsageTeamSpeed-3]
|
_ = x[ValueUsageTeamSpeed-3]
|
||||||
_ = x[ValueUsageTeamStamina-4]
|
_ = x[ValueUsageTeamStamina-4]
|
||||||
_ = x[ValueUsageTeamPower-5]
|
_ = x[ValueUsageTeamPower-5]
|
||||||
_ = x[ValueUsageTeamGuts-6]
|
_ = x[ValueUsageTeamGuts-6]
|
||||||
_ = x[ValueUsageTeamWit-7]
|
_ = x[ValueUsageTeamWit-7]
|
||||||
|
_ = x[ValueUsageRandom-8]
|
||||||
|
_ = x[ValueUsageRandom2-9]
|
||||||
|
_ = x[ValueUsageClimax-10]
|
||||||
|
_ = x[ValueUsageMaxStat-13]
|
||||||
|
_ = x[ValueUsageGreenCount-14]
|
||||||
|
_ = x[ValueUsageDistAdd-19]
|
||||||
|
_ = x[ValueUsageMidSideBlock-20]
|
||||||
|
_ = x[ValueUsageSpeed-22]
|
||||||
|
_ = x[ValueUsageSpeed2-23]
|
||||||
|
_ = x[ValueUsageArcPotential-24]
|
||||||
|
_ = x[ValueUsageMaxLead-25]
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_AbilityValueUsage_name_0 = "directly"
|
_AbilityValueUsage_name_0 = "directlyscaling with the number of skillsscaling with team Speedscaling with team Staminascaling with team Powerscaling with team Gutsscaling with team Witwith a random 0× to 0.04× multiplierwith a random 0× to 0.04× multiplierscaling with the number of races won in training"
|
||||||
_AbilityValueUsage_name_1 = "scaling with team Speedscaling with team Staminascaling with team Powerscaling with team Gutsscaling with team Wit"
|
_AbilityValueUsage_name_1 = "scaling with the highest raw statscaling with the number of Passive skills activated"
|
||||||
|
_AbilityValueUsage_name_2 = "plus extra when far from the leadscaling with mid-race phase blocked side time"
|
||||||
|
_AbilityValueUsage_name_3 = "scaling with overall speedscaling with overall speedscaling with L'Arc global potentialscaling with the longest lead obtained in the first ⅔"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_AbilityValueUsage_index_1 = [...]uint8{0, 23, 48, 71, 93, 114}
|
_AbilityValueUsage_index_0 = [...]uint16{0, 8, 41, 64, 89, 112, 134, 155, 193, 231, 279}
|
||||||
|
_AbilityValueUsage_index_1 = [...]uint8{0, 33, 84}
|
||||||
|
_AbilityValueUsage_index_2 = [...]uint8{0, 33, 78}
|
||||||
|
_AbilityValueUsage_index_3 = [...]uint8{0, 26, 52, 87, 142}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i AbilityValueUsage) String() string {
|
func (i AbilityValueUsage) String() string {
|
||||||
switch {
|
switch {
|
||||||
case i == 1:
|
case 1 <= i && i <= 10:
|
||||||
return _AbilityValueUsage_name_0
|
i -= 1
|
||||||
case 3 <= i && i <= 7:
|
return _AbilityValueUsage_name_0[_AbilityValueUsage_index_0[i]:_AbilityValueUsage_index_0[i+1]]
|
||||||
i -= 3
|
case 13 <= i && i <= 14:
|
||||||
|
i -= 13
|
||||||
return _AbilityValueUsage_name_1[_AbilityValueUsage_index_1[i]:_AbilityValueUsage_index_1[i+1]]
|
return _AbilityValueUsage_name_1[_AbilityValueUsage_index_1[i]:_AbilityValueUsage_index_1[i+1]]
|
||||||
|
case 19 <= i && i <= 20:
|
||||||
|
i -= 19
|
||||||
|
return _AbilityValueUsage_name_2[_AbilityValueUsage_index_2[i]:_AbilityValueUsage_index_2[i+1]]
|
||||||
|
case 22 <= i && i <= 25:
|
||||||
|
i -= 22
|
||||||
|
return _AbilityValueUsage_name_3[_AbilityValueUsage_index_3[i]:_AbilityValueUsage_index_3[i+1]]
|
||||||
default:
|
default:
|
||||||
return "AbilityValueUsage(" + strconv.FormatInt(int64(i), 10) + ")"
|
return "AbilityValueUsage(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
}
|
}
|
||||||
|
|||||||
17
horse/character.kk
Normal file
17
horse/character.kk
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
module horse/character
|
||||||
|
|
||||||
|
import horse/game-id
|
||||||
|
|
||||||
|
pub struct character-detail
|
||||||
|
character-id: character-id
|
||||||
|
name: string
|
||||||
|
|
||||||
|
pub fun detail(
|
||||||
|
c: character-id,
|
||||||
|
?character/show: (character-id) -> string
|
||||||
|
): character-detail
|
||||||
|
Character-detail(c, c.show)
|
||||||
|
|
||||||
|
pub fun character-detail/show(d: character-detail): string
|
||||||
|
val Character-detail(Character-id(id), name) = d
|
||||||
|
name ++ " (ID " ++ id.show ++ ")"
|
||||||
63
horse/game-id.kk
Normal file
63
horse/game-id.kk
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
module horse/game-id
|
||||||
|
|
||||||
|
// Game ID for characters, cards, skills, races, &c.
|
||||||
|
// Values for different categories may overlap.
|
||||||
|
alias game-id = int
|
||||||
|
|
||||||
|
// Specific game ID types.
|
||||||
|
// I've already made mistakes with ID categories and I haven't even committed this file yet.
|
||||||
|
|
||||||
|
// Game ID for characters.
|
||||||
|
// Generally numbers in the range 1000-9999.
|
||||||
|
pub struct character-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for trainees, i.e. costume instances of characters.
|
||||||
|
// Generally a character ID with two digits appended.
|
||||||
|
pub struct trainee-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for skills.
|
||||||
|
pub struct skill-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for skill groups.
|
||||||
|
pub struct skill-group-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for skill icons.
|
||||||
|
pub struct skill-icon-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for races,
|
||||||
|
// i.e. "Tenno Sho (Spring)" and not "Tenno Sho (Spring) at Kyoto Racecourse."
|
||||||
|
pub struct race-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for race thumbnails.
|
||||||
|
pub struct race-thumbnail-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// Game ID for saddles,
|
||||||
|
// i.e. one or more race wins that appear as a title.
|
||||||
|
pub struct saddle-id
|
||||||
|
game-id: game-id
|
||||||
|
|
||||||
|
// order2 comparison between any game ID types.
|
||||||
|
pub inline fun order2(x: a, y: a, ?a/game-id: (a) -> game-id): order2<a>
|
||||||
|
match x.game-id.cmp(y.game-id)
|
||||||
|
Lt -> Lt2(x, y)
|
||||||
|
Eq -> Eq2(x)
|
||||||
|
Gt -> Gt2(x, y)
|
||||||
|
|
||||||
|
// Comparison between any game ID types.
|
||||||
|
pub inline fun cmp(x: a, y: a, ?a/game-id: (a) -> game-id): order
|
||||||
|
x.game-id.cmp(y.game-id)
|
||||||
|
|
||||||
|
// Equality between any game ID types.
|
||||||
|
pub inline fun (==)(x: a, y: a, ?a/game-id: (a) -> game-id): bool
|
||||||
|
x.game-id == y.game-id
|
||||||
|
|
||||||
|
// Check whether a game ID is valid, i.e. nonzero.
|
||||||
|
pub inline fun is-valid(x: a, ?a/game-id: (a) -> game-id): bool
|
||||||
|
x.game-id != 0
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2014
horse/global/race.go
Normal file
2014
horse/global/race.go
Normal file
File diff suppressed because it is too large
Load Diff
2052
horse/global/race.kk
Normal file
2052
horse/global/race.kk
Normal file
File diff suppressed because it is too large
Load Diff
1107
horse/global/saddle.go
Normal file
1107
horse/global/saddle.go
Normal file
File diff suppressed because it is too large
Load Diff
985
horse/global/saddle.kk
Normal file
985
horse/global/saddle.kk
Normal file
@@ -0,0 +1,985 @@
|
|||||||
|
module horse/global/saddle
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import horse/game-id
|
||||||
|
pub import horse/race
|
||||||
|
pub import horse/global/race
|
||||||
|
|
||||||
|
// Enumeration of all saddles for type-safe programming.
|
||||||
|
pub type saddle
|
||||||
|
Classic-Triple-Crown
|
||||||
|
Senior-Autumn-Triple-Crown
|
||||||
|
Triple-Tiara
|
||||||
|
Senior-Spring-Triple-Crown
|
||||||
|
Tenno-Sweep
|
||||||
|
Dual-Grand-Prix
|
||||||
|
Dual-Miles
|
||||||
|
Dual-Sprints
|
||||||
|
Dual-Dirts
|
||||||
|
Arima-Kinen
|
||||||
|
Japan-C
|
||||||
|
Japanese-Derby
|
||||||
|
Tenno-Sho-Spring
|
||||||
|
Takarazuka-Kinen
|
||||||
|
Tenno-Sho-Autumn
|
||||||
|
Kikuka-Sho
|
||||||
|
Osaka-Hai
|
||||||
|
Satsuki-Sho
|
||||||
|
Japanese-Oaks
|
||||||
|
Takamatsunomiya-Kinen
|
||||||
|
Yasuda-Kinen
|
||||||
|
Sprinters-S
|
||||||
|
Mile-Ch
|
||||||
|
Oka-Sho
|
||||||
|
Victoria-Mile
|
||||||
|
Queen-Elizabeth-II-Cup
|
||||||
|
NHK-Mile-C
|
||||||
|
Shuka-Sho
|
||||||
|
Champions-C
|
||||||
|
February-S
|
||||||
|
JBC-Classic
|
||||||
|
Tokyo-Daishoten
|
||||||
|
Asahi-Hai-FS
|
||||||
|
Hopeful-S
|
||||||
|
Hanshin-JF
|
||||||
|
Teio-Sho
|
||||||
|
JBC-Sprint
|
||||||
|
JD-Derby
|
||||||
|
JBC-L-Classic
|
||||||
|
Nikkei-Shinshun-Hai
|
||||||
|
Tokai-S
|
||||||
|
American-JCC
|
||||||
|
Kyoto-Kinen
|
||||||
|
Nakayama-Kinen
|
||||||
|
Yayoi-Sho
|
||||||
|
Kinko-Sho
|
||||||
|
Fillies-Revue
|
||||||
|
Hanshin-Daishoten
|
||||||
|
Spring-S
|
||||||
|
Nikkei-Sho
|
||||||
|
Hanshin-Umamusume-S
|
||||||
|
New-Zealand-T
|
||||||
|
Yomiuri-Milers-C
|
||||||
|
Flora-S
|
||||||
|
Aoba-Sho
|
||||||
|
Kyoto-Shimbun-Hai
|
||||||
|
Keio-Hai-Spring-C
|
||||||
|
Meguro-Kinen
|
||||||
|
Sapporo-Kinen
|
||||||
|
Centaur-S
|
||||||
|
Rose-S
|
||||||
|
St-Lite-Kinen
|
||||||
|
Kobe-Shimbun-Hai
|
||||||
|
All-Comers
|
||||||
|
Mainichi-Okan
|
||||||
|
Kyoto-Daishoten
|
||||||
|
Fuchu-Umamusume-S
|
||||||
|
Swan-S
|
||||||
|
Keio-Hai-Junior-S
|
||||||
|
Copa-Republica-Argentina
|
||||||
|
Daily-Hai-Junior-S
|
||||||
|
Stayers-S
|
||||||
|
Hanshin-C
|
||||||
|
Kyoto-Kimpai
|
||||||
|
Nakayama-Kimpai
|
||||||
|
Shinzan-Kinen
|
||||||
|
Fairy-S
|
||||||
|
Aichi-Hai
|
||||||
|
Keisei-Hai
|
||||||
|
Silk-Road-S
|
||||||
|
Negishi-S
|
||||||
|
Kisaragi-Sho
|
||||||
|
Tokyo-Shimbun-Hai
|
||||||
|
Queen-C
|
||||||
|
Kyodo-News-Hai
|
||||||
|
Kyoto-Umamusume-S
|
||||||
|
Diamond-S
|
||||||
|
Kokura-Daishoten
|
||||||
|
Arlington-C
|
||||||
|
Hankyu-Hai
|
||||||
|
Tulip-Sho
|
||||||
|
Ocean-S
|
||||||
|
Nakayama-Umamusume-S
|
||||||
|
Falcon-S
|
||||||
|
Flower-C
|
||||||
|
Mainichi-Hai
|
||||||
|
March-S
|
||||||
|
Lord-Derby-CT
|
||||||
|
Antares-S
|
||||||
|
Fukushima-Umamusume-S
|
||||||
|
Niigata-Daishoten
|
||||||
|
Heian-S
|
||||||
|
Naruo-Kinen
|
||||||
|
Mermaid-S
|
||||||
|
Epsom-C
|
||||||
|
Unicorn-S
|
||||||
|
Hakodate-Sprint-S
|
||||||
|
CBC-Sho
|
||||||
|
Radio-Nikkei-Sho
|
||||||
|
Procyon-S
|
||||||
|
Tanabata-Sho
|
||||||
|
Hakodate-Kinen
|
||||||
|
Chukyo-Kinen
|
||||||
|
Hakodate-Junior-S
|
||||||
|
Ibis-Summer-D
|
||||||
|
Queen-S
|
||||||
|
Kokura-Kinen
|
||||||
|
Leopard-S
|
||||||
|
Sekiya-Kinen
|
||||||
|
Elm-S
|
||||||
|
Kitakyushu-Kinen
|
||||||
|
Niigata-Junior-S
|
||||||
|
Keeneland-C
|
||||||
|
Sapporo-Junior-S
|
||||||
|
Kokura-Junior-S
|
||||||
|
Niigata-Kinen
|
||||||
|
Shion-S
|
||||||
|
Keisei-Hai-AH
|
||||||
|
Sirius-S
|
||||||
|
Saudi-Arabia-RC
|
||||||
|
Fuji-S
|
||||||
|
Artemis-S
|
||||||
|
Fantasy-S
|
||||||
|
Miyako-S
|
||||||
|
Musashino-S
|
||||||
|
Fukushima-Kinen
|
||||||
|
Tokyo-Sports-Hai-Junior-S
|
||||||
|
Kyoto-Junior-S
|
||||||
|
Keihan-Hai
|
||||||
|
Challenge-C
|
||||||
|
Chunichi-Shimbun-Hai
|
||||||
|
Capella-S
|
||||||
|
Turquoise-S
|
||||||
|
Classic-Triple-Crown-Alt144
|
||||||
|
Senior-Spring-Triple-Crown-Alt145
|
||||||
|
Dual-Grand-Prix-Alt146
|
||||||
|
Takarazuka-Kinen-Alt147
|
||||||
|
Kikuka-Sho-Alt148
|
||||||
|
Spring-S-Alt149
|
||||||
|
Aoi-S
|
||||||
|
Senior-Spring-Triple-Crown-Alt151
|
||||||
|
Tenno-Sweep-Alt152
|
||||||
|
Tenno-Sho-Spring-Alt153
|
||||||
|
Classic-Triple-Crown-Alt154
|
||||||
|
Satsuki-Sho-Alt155
|
||||||
|
|
||||||
|
// Get the saddle ID for a saddle.
|
||||||
|
pub fun saddle-id(s: saddle): saddle-id
|
||||||
|
match s
|
||||||
|
Classic-Triple-Crown -> Saddle-id(1)
|
||||||
|
Senior-Autumn-Triple-Crown -> Saddle-id(2)
|
||||||
|
Triple-Tiara -> Saddle-id(3)
|
||||||
|
Senior-Spring-Triple-Crown -> Saddle-id(4)
|
||||||
|
Tenno-Sweep -> Saddle-id(5)
|
||||||
|
Dual-Grand-Prix -> Saddle-id(6)
|
||||||
|
Dual-Miles -> Saddle-id(7)
|
||||||
|
Dual-Sprints -> Saddle-id(8)
|
||||||
|
Dual-Dirts -> Saddle-id(9)
|
||||||
|
Arima-Kinen -> Saddle-id(10)
|
||||||
|
Japan-C -> Saddle-id(11)
|
||||||
|
Japanese-Derby -> Saddle-id(12)
|
||||||
|
Tenno-Sho-Spring -> Saddle-id(13)
|
||||||
|
Takarazuka-Kinen -> Saddle-id(14)
|
||||||
|
Tenno-Sho-Autumn -> Saddle-id(15)
|
||||||
|
Kikuka-Sho -> Saddle-id(16)
|
||||||
|
Osaka-Hai -> Saddle-id(17)
|
||||||
|
Satsuki-Sho -> Saddle-id(18)
|
||||||
|
Japanese-Oaks -> Saddle-id(19)
|
||||||
|
Takamatsunomiya-Kinen -> Saddle-id(20)
|
||||||
|
Yasuda-Kinen -> Saddle-id(21)
|
||||||
|
Sprinters-S -> Saddle-id(22)
|
||||||
|
Mile-Ch -> Saddle-id(23)
|
||||||
|
Oka-Sho -> Saddle-id(24)
|
||||||
|
Victoria-Mile -> Saddle-id(25)
|
||||||
|
Queen-Elizabeth-II-Cup -> Saddle-id(26)
|
||||||
|
NHK-Mile-C -> Saddle-id(27)
|
||||||
|
Shuka-Sho -> Saddle-id(28)
|
||||||
|
Champions-C -> Saddle-id(29)
|
||||||
|
February-S -> Saddle-id(30)
|
||||||
|
JBC-Classic -> Saddle-id(31)
|
||||||
|
Tokyo-Daishoten -> Saddle-id(32)
|
||||||
|
Asahi-Hai-FS -> Saddle-id(33)
|
||||||
|
Hopeful-S -> Saddle-id(34)
|
||||||
|
Hanshin-JF -> Saddle-id(35)
|
||||||
|
Teio-Sho -> Saddle-id(36)
|
||||||
|
JBC-Sprint -> Saddle-id(37)
|
||||||
|
JD-Derby -> Saddle-id(38)
|
||||||
|
JBC-L-Classic -> Saddle-id(39)
|
||||||
|
Nikkei-Shinshun-Hai -> Saddle-id(40)
|
||||||
|
Tokai-S -> Saddle-id(41)
|
||||||
|
American-JCC -> Saddle-id(42)
|
||||||
|
Kyoto-Kinen -> Saddle-id(43)
|
||||||
|
Nakayama-Kinen -> Saddle-id(44)
|
||||||
|
Yayoi-Sho -> Saddle-id(45)
|
||||||
|
Kinko-Sho -> Saddle-id(46)
|
||||||
|
Fillies-Revue -> Saddle-id(47)
|
||||||
|
Hanshin-Daishoten -> Saddle-id(48)
|
||||||
|
Spring-S -> Saddle-id(49)
|
||||||
|
Nikkei-Sho -> Saddle-id(50)
|
||||||
|
Hanshin-Umamusume-S -> Saddle-id(51)
|
||||||
|
New-Zealand-T -> Saddle-id(52)
|
||||||
|
Yomiuri-Milers-C -> Saddle-id(53)
|
||||||
|
Flora-S -> Saddle-id(54)
|
||||||
|
Aoba-Sho -> Saddle-id(55)
|
||||||
|
Kyoto-Shimbun-Hai -> Saddle-id(56)
|
||||||
|
Keio-Hai-Spring-C -> Saddle-id(57)
|
||||||
|
Meguro-Kinen -> Saddle-id(58)
|
||||||
|
Sapporo-Kinen -> Saddle-id(59)
|
||||||
|
Centaur-S -> Saddle-id(60)
|
||||||
|
Rose-S -> Saddle-id(61)
|
||||||
|
St-Lite-Kinen -> Saddle-id(62)
|
||||||
|
Kobe-Shimbun-Hai -> Saddle-id(63)
|
||||||
|
All-Comers -> Saddle-id(64)
|
||||||
|
Mainichi-Okan -> Saddle-id(65)
|
||||||
|
Kyoto-Daishoten -> Saddle-id(66)
|
||||||
|
Fuchu-Umamusume-S -> Saddle-id(67)
|
||||||
|
Swan-S -> Saddle-id(68)
|
||||||
|
Keio-Hai-Junior-S -> Saddle-id(69)
|
||||||
|
Copa-Republica-Argentina -> Saddle-id(70)
|
||||||
|
Daily-Hai-Junior-S -> Saddle-id(71)
|
||||||
|
Stayers-S -> Saddle-id(72)
|
||||||
|
Hanshin-C -> Saddle-id(73)
|
||||||
|
Kyoto-Kimpai -> Saddle-id(74)
|
||||||
|
Nakayama-Kimpai -> Saddle-id(75)
|
||||||
|
Shinzan-Kinen -> Saddle-id(76)
|
||||||
|
Fairy-S -> Saddle-id(77)
|
||||||
|
Aichi-Hai -> Saddle-id(78)
|
||||||
|
Keisei-Hai -> Saddle-id(79)
|
||||||
|
Silk-Road-S -> Saddle-id(80)
|
||||||
|
Negishi-S -> Saddle-id(81)
|
||||||
|
Kisaragi-Sho -> Saddle-id(82)
|
||||||
|
Tokyo-Shimbun-Hai -> Saddle-id(83)
|
||||||
|
Queen-C -> Saddle-id(84)
|
||||||
|
Kyodo-News-Hai -> Saddle-id(85)
|
||||||
|
Kyoto-Umamusume-S -> Saddle-id(86)
|
||||||
|
Diamond-S -> Saddle-id(87)
|
||||||
|
Kokura-Daishoten -> Saddle-id(88)
|
||||||
|
Arlington-C -> Saddle-id(89)
|
||||||
|
Hankyu-Hai -> Saddle-id(90)
|
||||||
|
Tulip-Sho -> Saddle-id(91)
|
||||||
|
Ocean-S -> Saddle-id(92)
|
||||||
|
Nakayama-Umamusume-S -> Saddle-id(93)
|
||||||
|
Falcon-S -> Saddle-id(94)
|
||||||
|
Flower-C -> Saddle-id(95)
|
||||||
|
Mainichi-Hai -> Saddle-id(96)
|
||||||
|
March-S -> Saddle-id(97)
|
||||||
|
Lord-Derby-CT -> Saddle-id(98)
|
||||||
|
Antares-S -> Saddle-id(99)
|
||||||
|
Fukushima-Umamusume-S -> Saddle-id(100)
|
||||||
|
Niigata-Daishoten -> Saddle-id(101)
|
||||||
|
Heian-S -> Saddle-id(102)
|
||||||
|
Naruo-Kinen -> Saddle-id(103)
|
||||||
|
Mermaid-S -> Saddle-id(104)
|
||||||
|
Epsom-C -> Saddle-id(105)
|
||||||
|
Unicorn-S -> Saddle-id(106)
|
||||||
|
Hakodate-Sprint-S -> Saddle-id(107)
|
||||||
|
CBC-Sho -> Saddle-id(108)
|
||||||
|
Radio-Nikkei-Sho -> Saddle-id(109)
|
||||||
|
Procyon-S -> Saddle-id(110)
|
||||||
|
Tanabata-Sho -> Saddle-id(111)
|
||||||
|
Hakodate-Kinen -> Saddle-id(112)
|
||||||
|
Chukyo-Kinen -> Saddle-id(113)
|
||||||
|
Hakodate-Junior-S -> Saddle-id(114)
|
||||||
|
Ibis-Summer-D -> Saddle-id(115)
|
||||||
|
Queen-S -> Saddle-id(116)
|
||||||
|
Kokura-Kinen -> Saddle-id(117)
|
||||||
|
Leopard-S -> Saddle-id(118)
|
||||||
|
Sekiya-Kinen -> Saddle-id(119)
|
||||||
|
Elm-S -> Saddle-id(120)
|
||||||
|
Kitakyushu-Kinen -> Saddle-id(121)
|
||||||
|
Niigata-Junior-S -> Saddle-id(122)
|
||||||
|
Keeneland-C -> Saddle-id(123)
|
||||||
|
Sapporo-Junior-S -> Saddle-id(124)
|
||||||
|
Kokura-Junior-S -> Saddle-id(125)
|
||||||
|
Niigata-Kinen -> Saddle-id(126)
|
||||||
|
Shion-S -> Saddle-id(127)
|
||||||
|
Keisei-Hai-AH -> Saddle-id(128)
|
||||||
|
Sirius-S -> Saddle-id(129)
|
||||||
|
Saudi-Arabia-RC -> Saddle-id(130)
|
||||||
|
Fuji-S -> Saddle-id(131)
|
||||||
|
Artemis-S -> Saddle-id(132)
|
||||||
|
Fantasy-S -> Saddle-id(133)
|
||||||
|
Miyako-S -> Saddle-id(134)
|
||||||
|
Musashino-S -> Saddle-id(135)
|
||||||
|
Fukushima-Kinen -> Saddle-id(136)
|
||||||
|
Tokyo-Sports-Hai-Junior-S -> Saddle-id(137)
|
||||||
|
Kyoto-Junior-S -> Saddle-id(138)
|
||||||
|
Keihan-Hai -> Saddle-id(139)
|
||||||
|
Challenge-C -> Saddle-id(140)
|
||||||
|
Chunichi-Shimbun-Hai -> Saddle-id(141)
|
||||||
|
Capella-S -> Saddle-id(142)
|
||||||
|
Turquoise-S -> Saddle-id(143)
|
||||||
|
Classic-Triple-Crown-Alt144 -> Saddle-id(144)
|
||||||
|
Senior-Spring-Triple-Crown-Alt145 -> Saddle-id(145)
|
||||||
|
Dual-Grand-Prix-Alt146 -> Saddle-id(146)
|
||||||
|
Takarazuka-Kinen-Alt147 -> Saddle-id(147)
|
||||||
|
Kikuka-Sho-Alt148 -> Saddle-id(148)
|
||||||
|
Spring-S-Alt149 -> Saddle-id(149)
|
||||||
|
Aoi-S -> Saddle-id(150)
|
||||||
|
Senior-Spring-Triple-Crown-Alt151 -> Saddle-id(151)
|
||||||
|
Tenno-Sweep-Alt152 -> Saddle-id(152)
|
||||||
|
Tenno-Sho-Spring-Alt153 -> Saddle-id(153)
|
||||||
|
Classic-Triple-Crown-Alt154 -> Saddle-id(154)
|
||||||
|
Satsuki-Sho-Alt155 -> Saddle-id(155)
|
||||||
|
|
||||||
|
// List of all saddles in ID order for easy iterating.
|
||||||
|
pub val all = [
|
||||||
|
Classic-Triple-Crown,
|
||||||
|
Senior-Autumn-Triple-Crown,
|
||||||
|
Triple-Tiara,
|
||||||
|
Senior-Spring-Triple-Crown,
|
||||||
|
Tenno-Sweep,
|
||||||
|
Dual-Grand-Prix,
|
||||||
|
Dual-Miles,
|
||||||
|
Dual-Sprints,
|
||||||
|
Dual-Dirts,
|
||||||
|
Arima-Kinen,
|
||||||
|
Japan-C,
|
||||||
|
Japanese-Derby,
|
||||||
|
Tenno-Sho-Spring,
|
||||||
|
Takarazuka-Kinen,
|
||||||
|
Tenno-Sho-Autumn,
|
||||||
|
Kikuka-Sho,
|
||||||
|
Osaka-Hai,
|
||||||
|
Satsuki-Sho,
|
||||||
|
Japanese-Oaks,
|
||||||
|
Takamatsunomiya-Kinen,
|
||||||
|
Yasuda-Kinen,
|
||||||
|
Sprinters-S,
|
||||||
|
Mile-Ch,
|
||||||
|
Oka-Sho,
|
||||||
|
Victoria-Mile,
|
||||||
|
Queen-Elizabeth-II-Cup,
|
||||||
|
NHK-Mile-C,
|
||||||
|
Shuka-Sho,
|
||||||
|
Champions-C,
|
||||||
|
February-S,
|
||||||
|
JBC-Classic,
|
||||||
|
Tokyo-Daishoten,
|
||||||
|
Asahi-Hai-FS,
|
||||||
|
Hopeful-S,
|
||||||
|
Hanshin-JF,
|
||||||
|
Teio-Sho,
|
||||||
|
JBC-Sprint,
|
||||||
|
JD-Derby,
|
||||||
|
JBC-L-Classic,
|
||||||
|
Nikkei-Shinshun-Hai,
|
||||||
|
Tokai-S,
|
||||||
|
American-JCC,
|
||||||
|
Kyoto-Kinen,
|
||||||
|
Nakayama-Kinen,
|
||||||
|
Yayoi-Sho,
|
||||||
|
Kinko-Sho,
|
||||||
|
Fillies-Revue,
|
||||||
|
Hanshin-Daishoten,
|
||||||
|
Spring-S,
|
||||||
|
Nikkei-Sho,
|
||||||
|
Hanshin-Umamusume-S,
|
||||||
|
New-Zealand-T,
|
||||||
|
Yomiuri-Milers-C,
|
||||||
|
Flora-S,
|
||||||
|
Aoba-Sho,
|
||||||
|
Kyoto-Shimbun-Hai,
|
||||||
|
Keio-Hai-Spring-C,
|
||||||
|
Meguro-Kinen,
|
||||||
|
Sapporo-Kinen,
|
||||||
|
Centaur-S,
|
||||||
|
Rose-S,
|
||||||
|
St-Lite-Kinen,
|
||||||
|
Kobe-Shimbun-Hai,
|
||||||
|
All-Comers,
|
||||||
|
Mainichi-Okan,
|
||||||
|
Kyoto-Daishoten,
|
||||||
|
Fuchu-Umamusume-S,
|
||||||
|
Swan-S,
|
||||||
|
Keio-Hai-Junior-S,
|
||||||
|
Copa-Republica-Argentina,
|
||||||
|
Daily-Hai-Junior-S,
|
||||||
|
Stayers-S,
|
||||||
|
Hanshin-C,
|
||||||
|
Kyoto-Kimpai,
|
||||||
|
Nakayama-Kimpai,
|
||||||
|
Shinzan-Kinen,
|
||||||
|
Fairy-S,
|
||||||
|
Aichi-Hai,
|
||||||
|
Keisei-Hai,
|
||||||
|
Silk-Road-S,
|
||||||
|
Negishi-S,
|
||||||
|
Kisaragi-Sho,
|
||||||
|
Tokyo-Shimbun-Hai,
|
||||||
|
Queen-C,
|
||||||
|
Kyodo-News-Hai,
|
||||||
|
Kyoto-Umamusume-S,
|
||||||
|
Diamond-S,
|
||||||
|
Kokura-Daishoten,
|
||||||
|
Arlington-C,
|
||||||
|
Hankyu-Hai,
|
||||||
|
Tulip-Sho,
|
||||||
|
Ocean-S,
|
||||||
|
Nakayama-Umamusume-S,
|
||||||
|
Falcon-S,
|
||||||
|
Flower-C,
|
||||||
|
Mainichi-Hai,
|
||||||
|
March-S,
|
||||||
|
Lord-Derby-CT,
|
||||||
|
Antares-S,
|
||||||
|
Fukushima-Umamusume-S,
|
||||||
|
Niigata-Daishoten,
|
||||||
|
Heian-S,
|
||||||
|
Naruo-Kinen,
|
||||||
|
Mermaid-S,
|
||||||
|
Epsom-C,
|
||||||
|
Unicorn-S,
|
||||||
|
Hakodate-Sprint-S,
|
||||||
|
CBC-Sho,
|
||||||
|
Radio-Nikkei-Sho,
|
||||||
|
Procyon-S,
|
||||||
|
Tanabata-Sho,
|
||||||
|
Hakodate-Kinen,
|
||||||
|
Chukyo-Kinen,
|
||||||
|
Hakodate-Junior-S,
|
||||||
|
Ibis-Summer-D,
|
||||||
|
Queen-S,
|
||||||
|
Kokura-Kinen,
|
||||||
|
Leopard-S,
|
||||||
|
Sekiya-Kinen,
|
||||||
|
Elm-S,
|
||||||
|
Kitakyushu-Kinen,
|
||||||
|
Niigata-Junior-S,
|
||||||
|
Keeneland-C,
|
||||||
|
Sapporo-Junior-S,
|
||||||
|
Kokura-Junior-S,
|
||||||
|
Niigata-Kinen,
|
||||||
|
Shion-S,
|
||||||
|
Keisei-Hai-AH,
|
||||||
|
Sirius-S,
|
||||||
|
Saudi-Arabia-RC,
|
||||||
|
Fuji-S,
|
||||||
|
Artemis-S,
|
||||||
|
Fantasy-S,
|
||||||
|
Miyako-S,
|
||||||
|
Musashino-S,
|
||||||
|
Fukushima-Kinen,
|
||||||
|
Tokyo-Sports-Hai-Junior-S,
|
||||||
|
Kyoto-Junior-S,
|
||||||
|
Keihan-Hai,
|
||||||
|
Challenge-C,
|
||||||
|
Chunichi-Shimbun-Hai,
|
||||||
|
Capella-S,
|
||||||
|
Turquoise-S,
|
||||||
|
Classic-Triple-Crown-Alt144,
|
||||||
|
Senior-Spring-Triple-Crown-Alt145,
|
||||||
|
Dual-Grand-Prix-Alt146,
|
||||||
|
Takarazuka-Kinen-Alt147,
|
||||||
|
Kikuka-Sho-Alt148,
|
||||||
|
Spring-S-Alt149,
|
||||||
|
Aoi-S,
|
||||||
|
Senior-Spring-Triple-Crown-Alt151,
|
||||||
|
Tenno-Sweep-Alt152,
|
||||||
|
Tenno-Sho-Spring-Alt153,
|
||||||
|
Classic-Triple-Crown-Alt154,
|
||||||
|
Satsuki-Sho-Alt155,
|
||||||
|
]
|
||||||
|
|
||||||
|
// Get the name for a saddle.
|
||||||
|
// Alternate versions of saddles have an indication of their ID in their names.
|
||||||
|
// If no saddle matches the ID, the result contains the numeric ID.
|
||||||
|
pub fun show(s: saddle-id): string
|
||||||
|
match s.game-id
|
||||||
|
1 -> "Classic Triple Crown"
|
||||||
|
2 -> "Senior Autumn Triple Crown"
|
||||||
|
3 -> "Triple Tiara"
|
||||||
|
4 -> "Senior Spring Triple Crown"
|
||||||
|
5 -> "Tenno Sweep"
|
||||||
|
6 -> "Dual Grand Prix"
|
||||||
|
7 -> "Dual Miles"
|
||||||
|
8 -> "Dual Sprints"
|
||||||
|
9 -> "Dual Dirts"
|
||||||
|
10 -> "Arima Kinen"
|
||||||
|
11 -> "Japan C."
|
||||||
|
12 -> "Japanese Derby"
|
||||||
|
13 -> "Tenno Sho (Spring)"
|
||||||
|
14 -> "Takarazuka Kinen"
|
||||||
|
15 -> "Tenno Sho (Autumn)"
|
||||||
|
16 -> "Kikuka Sho"
|
||||||
|
17 -> "Osaka Hai"
|
||||||
|
18 -> "Satsuki Sho"
|
||||||
|
19 -> "Japanese Oaks"
|
||||||
|
20 -> "Takamatsunomiya Kinen"
|
||||||
|
21 -> "Yasuda Kinen"
|
||||||
|
22 -> "Sprinters S."
|
||||||
|
23 -> "Mile Ch."
|
||||||
|
24 -> "Oka Sho"
|
||||||
|
25 -> "Victoria Mile"
|
||||||
|
26 -> "Queen Elizabeth II Cup"
|
||||||
|
27 -> "NHK Mile C."
|
||||||
|
28 -> "Shuka Sho"
|
||||||
|
29 -> "Champions C."
|
||||||
|
30 -> "February S."
|
||||||
|
31 -> "JBC Classic"
|
||||||
|
32 -> "Tokyo Daishoten"
|
||||||
|
33 -> "Asahi Hai F.S."
|
||||||
|
34 -> "Hopeful S."
|
||||||
|
35 -> "Hanshin J.F."
|
||||||
|
36 -> "Teio Sho"
|
||||||
|
37 -> "JBC Sprint"
|
||||||
|
38 -> "J.D. Derby"
|
||||||
|
39 -> "JBC L. Classic"
|
||||||
|
40 -> "Nikkei Shinshun Hai"
|
||||||
|
41 -> "Tokai S."
|
||||||
|
42 -> "American JCC"
|
||||||
|
43 -> "Kyoto Kinen"
|
||||||
|
44 -> "Nakayama Kinen"
|
||||||
|
45 -> "Yayoi Sho"
|
||||||
|
46 -> "Kinko Sho"
|
||||||
|
47 -> "Fillies' Revue"
|
||||||
|
48 -> "Hanshin Daishoten"
|
||||||
|
49 -> "Spring S."
|
||||||
|
50 -> "Nikkei Sho"
|
||||||
|
51 -> "Hanshin Umamusume S."
|
||||||
|
52 -> "New Zealand T."
|
||||||
|
53 -> "Yomiuri Milers C."
|
||||||
|
54 -> "Flora S."
|
||||||
|
55 -> "Aoba Sho"
|
||||||
|
56 -> "Kyoto Shimbun Hai"
|
||||||
|
57 -> "Keio Hai Spring C."
|
||||||
|
58 -> "Meguro Kinen"
|
||||||
|
59 -> "Sapporo Kinen"
|
||||||
|
60 -> "Centaur S."
|
||||||
|
61 -> "Rose S."
|
||||||
|
62 -> "St. Lite Kinen"
|
||||||
|
63 -> "Kobe Shimbun Hai"
|
||||||
|
64 -> "All Comers"
|
||||||
|
65 -> "Mainichi Okan"
|
||||||
|
66 -> "Kyoto Daishoten"
|
||||||
|
67 -> "Fuchu Umamusume S."
|
||||||
|
68 -> "Swan S."
|
||||||
|
69 -> "Keio Hai Junior S."
|
||||||
|
70 -> "Copa Republica Argentina"
|
||||||
|
71 -> "Daily Hai Junior S."
|
||||||
|
72 -> "Stayers S."
|
||||||
|
73 -> "Hanshin C."
|
||||||
|
74 -> "Kyoto Kimpai"
|
||||||
|
75 -> "Nakayama Kimpai"
|
||||||
|
76 -> "Shinzan Kinen"
|
||||||
|
77 -> "Fairy S."
|
||||||
|
78 -> "Aichi Hai"
|
||||||
|
79 -> "Keisei Hai"
|
||||||
|
80 -> "Silk Road S."
|
||||||
|
81 -> "Negishi S."
|
||||||
|
82 -> "Kisaragi Sho"
|
||||||
|
83 -> "Tokyo Shimbun Hai"
|
||||||
|
84 -> "Queen C."
|
||||||
|
85 -> "Kyodo News Hai"
|
||||||
|
86 -> "Kyoto Umamusume S."
|
||||||
|
87 -> "Diamond S."
|
||||||
|
88 -> "Kokura Daishoten"
|
||||||
|
89 -> "Arlington C."
|
||||||
|
90 -> "Hankyu Hai"
|
||||||
|
91 -> "Tulip Sho"
|
||||||
|
92 -> "Ocean S."
|
||||||
|
93 -> "Nakayama Umamusume S."
|
||||||
|
94 -> "Falcon S."
|
||||||
|
95 -> "Flower C."
|
||||||
|
96 -> "Mainichi Hai"
|
||||||
|
97 -> "March S."
|
||||||
|
98 -> "Lord Derby C.T."
|
||||||
|
99 -> "Antares S."
|
||||||
|
100 -> "Fukushima Umamusume S."
|
||||||
|
101 -> "Niigata Daishoten"
|
||||||
|
102 -> "Heian S."
|
||||||
|
103 -> "Naruo Kinen"
|
||||||
|
104 -> "Mermaid S."
|
||||||
|
105 -> "Epsom C."
|
||||||
|
106 -> "Unicorn S."
|
||||||
|
107 -> "Hakodate Sprint S."
|
||||||
|
108 -> "CBC Sho"
|
||||||
|
109 -> "Radio Nikkei Sho"
|
||||||
|
110 -> "Procyon S."
|
||||||
|
111 -> "Tanabata Sho"
|
||||||
|
112 -> "Hakodate Kinen"
|
||||||
|
113 -> "Chukyo Kinen"
|
||||||
|
114 -> "Hakodate Junior S."
|
||||||
|
115 -> "Ibis Summer D."
|
||||||
|
116 -> "Queen S."
|
||||||
|
117 -> "Kokura Kinen"
|
||||||
|
118 -> "Leopard S."
|
||||||
|
119 -> "Sekiya Kinen"
|
||||||
|
120 -> "Elm S."
|
||||||
|
121 -> "Kitakyushu Kinen"
|
||||||
|
122 -> "Niigata Junior S."
|
||||||
|
123 -> "Keeneland C."
|
||||||
|
124 -> "Sapporo Junior S."
|
||||||
|
125 -> "Kokura Junior S."
|
||||||
|
126 -> "Niigata Kinen"
|
||||||
|
127 -> "Shion S."
|
||||||
|
128 -> "Keisei Hai A.H."
|
||||||
|
129 -> "Sirius S."
|
||||||
|
130 -> "Saudi Arabia R.C."
|
||||||
|
131 -> "Fuji S."
|
||||||
|
132 -> "Artemis S."
|
||||||
|
133 -> "Fantasy S."
|
||||||
|
134 -> "Miyako S."
|
||||||
|
135 -> "Musashino S."
|
||||||
|
136 -> "Fukushima Kinen"
|
||||||
|
137 -> "Tokyo Sports Hai Junior S."
|
||||||
|
138 -> "Kyoto Junior S."
|
||||||
|
139 -> "Keihan Hai"
|
||||||
|
140 -> "Challenge C."
|
||||||
|
141 -> "Chunichi Shimbun Hai"
|
||||||
|
142 -> "Capella S."
|
||||||
|
143 -> "Turquoise S."
|
||||||
|
144 -> "Classic Triple Crown" ++ " (Alternate 144)"
|
||||||
|
145 -> "Senior Spring Triple Crown" ++ " (Alternate 145)"
|
||||||
|
146 -> "Dual Grand Prix" ++ " (Alternate 146)"
|
||||||
|
147 -> "Takarazuka Kinen" ++ " (Alternate 147)"
|
||||||
|
148 -> "Kikuka Sho" ++ " (Alternate 148)"
|
||||||
|
149 -> "Spring S." ++ " (Alternate 149)"
|
||||||
|
150 -> "Aoi S."
|
||||||
|
151 -> "Senior Spring Triple Crown" ++ " (Alternate 151)"
|
||||||
|
152 -> "Tenno Sweep" ++ " (Alternate 152)"
|
||||||
|
153 -> "Tenno Sho (Spring)" ++ " (Alternate 153)"
|
||||||
|
154 -> "Classic Triple Crown" ++ " (Alternate 154)"
|
||||||
|
155 -> "Satsuki Sho" ++ " (Alternate 155)"
|
||||||
|
x -> "saddle " ++ x.show
|
||||||
|
|
||||||
|
// Get the list of races that entitle a horse to a saddle.
|
||||||
|
// If no saddle matches the ID, the result is the empty list.
|
||||||
|
pub fun races(s: saddle-id): list<race-id>
|
||||||
|
match s.game-id
|
||||||
|
1 -> [Race-id(100501), Race-id(101001), Race-id(101501), ]
|
||||||
|
2 -> [Race-id(101601), Race-id(101901), Race-id(102301), ]
|
||||||
|
3 -> [Race-id(100401), Race-id(100901), Race-id(101401), ]
|
||||||
|
4 -> [Race-id(100301), Race-id(100601), Race-id(101201), ]
|
||||||
|
5 -> [Race-id(100601), Race-id(101601), ]
|
||||||
|
6 -> [Race-id(101201), Race-id(102301), ]
|
||||||
|
7 -> [Race-id(101101), Race-id(101801), ]
|
||||||
|
8 -> [Race-id(101301), Race-id(100201), ]
|
||||||
|
9 -> [Race-id(100101), Race-id(102001), ]
|
||||||
|
10 -> [Race-id(102301), ]
|
||||||
|
11 -> [Race-id(101901), ]
|
||||||
|
12 -> [Race-id(101001), ]
|
||||||
|
13 -> [Race-id(100601), ]
|
||||||
|
14 -> [Race-id(101201), ]
|
||||||
|
15 -> [Race-id(101601), ]
|
||||||
|
16 -> [Race-id(101501), ]
|
||||||
|
17 -> [Race-id(100301), ]
|
||||||
|
18 -> [Race-id(100501), ]
|
||||||
|
19 -> [Race-id(100901), ]
|
||||||
|
20 -> [Race-id(100201), ]
|
||||||
|
21 -> [Race-id(101101), ]
|
||||||
|
22 -> [Race-id(101301), ]
|
||||||
|
23 -> [Race-id(101801), ]
|
||||||
|
24 -> [Race-id(100401), ]
|
||||||
|
25 -> [Race-id(100801), ]
|
||||||
|
26 -> [Race-id(101701), ]
|
||||||
|
27 -> [Race-id(100701), ]
|
||||||
|
28 -> [Race-id(101401), ]
|
||||||
|
29 -> [Race-id(102001), ]
|
||||||
|
30 -> [Race-id(100101), ]
|
||||||
|
31 -> [Race-id(110501), ]
|
||||||
|
32 -> [Race-id(110601), ]
|
||||||
|
33 -> [Race-id(102201), ]
|
||||||
|
34 -> [Race-id(102401), ]
|
||||||
|
35 -> [Race-id(102101), ]
|
||||||
|
36 -> [Race-id(110101), ]
|
||||||
|
37 -> [Race-id(110401), ]
|
||||||
|
38 -> [Race-id(110201), ]
|
||||||
|
39 -> [Race-id(110301), ]
|
||||||
|
40 -> [Race-id(200101), ]
|
||||||
|
41 -> [Race-id(200201), ]
|
||||||
|
42 -> [Race-id(200301), ]
|
||||||
|
43 -> [Race-id(200401), ]
|
||||||
|
44 -> [Race-id(200501), ]
|
||||||
|
45 -> [Race-id(200601), ]
|
||||||
|
46 -> [Race-id(200701), ]
|
||||||
|
47 -> [Race-id(200801), ]
|
||||||
|
48 -> [Race-id(200901), ]
|
||||||
|
49 -> [Race-id(201001), ]
|
||||||
|
50 -> [Race-id(201101), ]
|
||||||
|
51 -> [Race-id(201201), ]
|
||||||
|
52 -> [Race-id(201301), ]
|
||||||
|
53 -> [Race-id(201401), ]
|
||||||
|
54 -> [Race-id(201501), ]
|
||||||
|
55 -> [Race-id(201601), ]
|
||||||
|
56 -> [Race-id(201701), ]
|
||||||
|
57 -> [Race-id(201801), ]
|
||||||
|
58 -> [Race-id(201901), ]
|
||||||
|
59 -> [Race-id(202001), ]
|
||||||
|
60 -> [Race-id(202101), ]
|
||||||
|
61 -> [Race-id(202201), ]
|
||||||
|
62 -> [Race-id(202301), ]
|
||||||
|
63 -> [Race-id(202401), ]
|
||||||
|
64 -> [Race-id(202501), ]
|
||||||
|
65 -> [Race-id(202601), ]
|
||||||
|
66 -> [Race-id(202701), ]
|
||||||
|
67 -> [Race-id(202801), ]
|
||||||
|
68 -> [Race-id(202901), ]
|
||||||
|
69 -> [Race-id(203001), ]
|
||||||
|
70 -> [Race-id(203101), ]
|
||||||
|
71 -> [Race-id(203201), ]
|
||||||
|
72 -> [Race-id(203301), ]
|
||||||
|
73 -> [Race-id(203401), ]
|
||||||
|
74 -> [Race-id(300101), ]
|
||||||
|
75 -> [Race-id(300201), ]
|
||||||
|
76 -> [Race-id(300301), ]
|
||||||
|
77 -> [Race-id(300401), ]
|
||||||
|
78 -> [Race-id(300501), ]
|
||||||
|
79 -> [Race-id(300601), ]
|
||||||
|
80 -> [Race-id(300701), ]
|
||||||
|
81 -> [Race-id(300801), ]
|
||||||
|
82 -> [Race-id(300901), ]
|
||||||
|
83 -> [Race-id(301001), ]
|
||||||
|
84 -> [Race-id(301101), ]
|
||||||
|
85 -> [Race-id(301201), ]
|
||||||
|
86 -> [Race-id(301301), ]
|
||||||
|
87 -> [Race-id(301401), ]
|
||||||
|
88 -> [Race-id(301501), ]
|
||||||
|
89 -> [Race-id(301601), ]
|
||||||
|
90 -> [Race-id(301701), ]
|
||||||
|
91 -> [Race-id(301801), ]
|
||||||
|
92 -> [Race-id(301901), ]
|
||||||
|
93 -> [Race-id(302001), ]
|
||||||
|
94 -> [Race-id(302101), ]
|
||||||
|
95 -> [Race-id(302201), ]
|
||||||
|
96 -> [Race-id(302301), ]
|
||||||
|
97 -> [Race-id(302401), ]
|
||||||
|
98 -> [Race-id(302501), ]
|
||||||
|
99 -> [Race-id(302601), ]
|
||||||
|
100 -> [Race-id(302701), ]
|
||||||
|
101 -> [Race-id(302801), ]
|
||||||
|
102 -> [Race-id(302901), ]
|
||||||
|
103 -> [Race-id(303001), ]
|
||||||
|
104 -> [Race-id(303101), ]
|
||||||
|
105 -> [Race-id(303201), ]
|
||||||
|
106 -> [Race-id(303301), ]
|
||||||
|
107 -> [Race-id(303401), ]
|
||||||
|
108 -> [Race-id(303501), ]
|
||||||
|
109 -> [Race-id(303601), ]
|
||||||
|
110 -> [Race-id(303701), ]
|
||||||
|
111 -> [Race-id(303801), ]
|
||||||
|
112 -> [Race-id(303901), ]
|
||||||
|
113 -> [Race-id(304001), ]
|
||||||
|
114 -> [Race-id(304101), ]
|
||||||
|
115 -> [Race-id(304201), ]
|
||||||
|
116 -> [Race-id(304301), ]
|
||||||
|
117 -> [Race-id(304401), ]
|
||||||
|
118 -> [Race-id(304501), ]
|
||||||
|
119 -> [Race-id(304601), ]
|
||||||
|
120 -> [Race-id(304701), ]
|
||||||
|
121 -> [Race-id(304801), ]
|
||||||
|
122 -> [Race-id(304901), ]
|
||||||
|
123 -> [Race-id(305001), ]
|
||||||
|
124 -> [Race-id(305101), ]
|
||||||
|
125 -> [Race-id(305201), ]
|
||||||
|
126 -> [Race-id(305301), ]
|
||||||
|
127 -> [Race-id(305401), ]
|
||||||
|
128 -> [Race-id(305501), ]
|
||||||
|
129 -> [Race-id(305601), ]
|
||||||
|
130 -> [Race-id(305701), ]
|
||||||
|
131 -> [Race-id(305801), ]
|
||||||
|
132 -> [Race-id(305901), ]
|
||||||
|
133 -> [Race-id(306001), ]
|
||||||
|
134 -> [Race-id(306101), ]
|
||||||
|
135 -> [Race-id(306201), ]
|
||||||
|
136 -> [Race-id(306301), ]
|
||||||
|
137 -> [Race-id(306401), ]
|
||||||
|
138 -> [Race-id(306501), ]
|
||||||
|
139 -> [Race-id(306601), ]
|
||||||
|
140 -> [Race-id(306701), ]
|
||||||
|
141 -> [Race-id(306801), ]
|
||||||
|
142 -> [Race-id(306901), ]
|
||||||
|
143 -> [Race-id(307001), ]
|
||||||
|
144 -> [Race-id(100501), Race-id(101001), Race-id(102601), ]
|
||||||
|
145 -> [Race-id(100301), Race-id(100601), Race-id(102501), ]
|
||||||
|
146 -> [Race-id(102501), Race-id(102301), ]
|
||||||
|
147 -> [Race-id(102501), ]
|
||||||
|
148 -> [Race-id(102601), ]
|
||||||
|
149 -> [Race-id(203501), ]
|
||||||
|
150 -> [Race-id(405001), ]
|
||||||
|
151 -> [Race-id(100301), Race-id(102701), Race-id(101201), ]
|
||||||
|
152 -> [Race-id(102701), Race-id(101601), ]
|
||||||
|
153 -> [Race-id(102701), ]
|
||||||
|
154 -> [Race-id(102801), Race-id(101001), Race-id(101501), ]
|
||||||
|
155 -> [Race-id(102801), ]
|
||||||
|
_ -> []
|
||||||
|
|
||||||
|
// Get a saddle's type.
|
||||||
|
// If no saddle matches the ID, the result is Honor.
|
||||||
|
pub fun saddle-type(s: saddle-id): saddle-type
|
||||||
|
match s.game-id
|
||||||
|
1 -> Honor
|
||||||
|
2 -> Honor
|
||||||
|
3 -> Honor
|
||||||
|
4 -> Honor
|
||||||
|
5 -> Honor
|
||||||
|
6 -> Honor
|
||||||
|
7 -> Honor
|
||||||
|
8 -> Honor
|
||||||
|
9 -> Honor
|
||||||
|
10 -> G1-Win
|
||||||
|
11 -> G1-Win
|
||||||
|
12 -> G1-Win
|
||||||
|
13 -> G1-Win
|
||||||
|
14 -> G1-Win
|
||||||
|
15 -> G1-Win
|
||||||
|
16 -> G1-Win
|
||||||
|
17 -> G1-Win
|
||||||
|
18 -> G1-Win
|
||||||
|
19 -> G1-Win
|
||||||
|
20 -> G1-Win
|
||||||
|
21 -> G1-Win
|
||||||
|
22 -> G1-Win
|
||||||
|
23 -> G1-Win
|
||||||
|
24 -> G1-Win
|
||||||
|
25 -> G1-Win
|
||||||
|
26 -> G1-Win
|
||||||
|
27 -> G1-Win
|
||||||
|
28 -> G1-Win
|
||||||
|
29 -> G1-Win
|
||||||
|
30 -> G1-Win
|
||||||
|
31 -> G1-Win
|
||||||
|
32 -> G1-Win
|
||||||
|
33 -> G1-Win
|
||||||
|
34 -> G1-Win
|
||||||
|
35 -> G1-Win
|
||||||
|
36 -> G1-Win
|
||||||
|
37 -> G1-Win
|
||||||
|
38 -> G1-Win
|
||||||
|
39 -> G1-Win
|
||||||
|
40 -> G2-Win
|
||||||
|
41 -> G2-Win
|
||||||
|
42 -> G2-Win
|
||||||
|
43 -> G2-Win
|
||||||
|
44 -> G2-Win
|
||||||
|
45 -> G2-Win
|
||||||
|
46 -> G2-Win
|
||||||
|
47 -> G2-Win
|
||||||
|
48 -> G2-Win
|
||||||
|
49 -> G2-Win
|
||||||
|
50 -> G2-Win
|
||||||
|
51 -> G2-Win
|
||||||
|
52 -> G2-Win
|
||||||
|
53 -> G2-Win
|
||||||
|
54 -> G2-Win
|
||||||
|
55 -> G2-Win
|
||||||
|
56 -> G2-Win
|
||||||
|
57 -> G2-Win
|
||||||
|
58 -> G2-Win
|
||||||
|
59 -> G2-Win
|
||||||
|
60 -> G2-Win
|
||||||
|
61 -> G2-Win
|
||||||
|
62 -> G2-Win
|
||||||
|
63 -> G2-Win
|
||||||
|
64 -> G2-Win
|
||||||
|
65 -> G2-Win
|
||||||
|
66 -> G2-Win
|
||||||
|
67 -> G2-Win
|
||||||
|
68 -> G2-Win
|
||||||
|
69 -> G2-Win
|
||||||
|
70 -> G2-Win
|
||||||
|
71 -> G2-Win
|
||||||
|
72 -> G2-Win
|
||||||
|
73 -> G2-Win
|
||||||
|
74 -> G3-Win
|
||||||
|
75 -> G3-Win
|
||||||
|
76 -> G3-Win
|
||||||
|
77 -> G3-Win
|
||||||
|
78 -> G3-Win
|
||||||
|
79 -> G3-Win
|
||||||
|
80 -> G3-Win
|
||||||
|
81 -> G3-Win
|
||||||
|
82 -> G3-Win
|
||||||
|
83 -> G3-Win
|
||||||
|
84 -> G3-Win
|
||||||
|
85 -> G3-Win
|
||||||
|
86 -> G3-Win
|
||||||
|
87 -> G3-Win
|
||||||
|
88 -> G3-Win
|
||||||
|
89 -> G3-Win
|
||||||
|
90 -> G3-Win
|
||||||
|
91 -> G2-Win
|
||||||
|
92 -> G3-Win
|
||||||
|
93 -> G3-Win
|
||||||
|
94 -> G3-Win
|
||||||
|
95 -> G3-Win
|
||||||
|
96 -> G3-Win
|
||||||
|
97 -> G3-Win
|
||||||
|
98 -> G3-Win
|
||||||
|
99 -> G3-Win
|
||||||
|
100 -> G3-Win
|
||||||
|
101 -> G3-Win
|
||||||
|
102 -> G3-Win
|
||||||
|
103 -> G3-Win
|
||||||
|
104 -> G3-Win
|
||||||
|
105 -> G3-Win
|
||||||
|
106 -> G3-Win
|
||||||
|
107 -> G3-Win
|
||||||
|
108 -> G3-Win
|
||||||
|
109 -> G3-Win
|
||||||
|
110 -> G3-Win
|
||||||
|
111 -> G3-Win
|
||||||
|
112 -> G3-Win
|
||||||
|
113 -> G3-Win
|
||||||
|
114 -> G3-Win
|
||||||
|
115 -> G3-Win
|
||||||
|
116 -> G3-Win
|
||||||
|
117 -> G3-Win
|
||||||
|
118 -> G3-Win
|
||||||
|
119 -> G3-Win
|
||||||
|
120 -> G3-Win
|
||||||
|
121 -> G3-Win
|
||||||
|
122 -> G3-Win
|
||||||
|
123 -> G3-Win
|
||||||
|
124 -> G3-Win
|
||||||
|
125 -> G3-Win
|
||||||
|
126 -> G3-Win
|
||||||
|
127 -> G3-Win
|
||||||
|
128 -> G3-Win
|
||||||
|
129 -> G3-Win
|
||||||
|
130 -> G3-Win
|
||||||
|
131 -> G2-Win
|
||||||
|
132 -> G3-Win
|
||||||
|
133 -> G3-Win
|
||||||
|
134 -> G3-Win
|
||||||
|
135 -> G3-Win
|
||||||
|
136 -> G3-Win
|
||||||
|
137 -> G3-Win
|
||||||
|
138 -> G3-Win
|
||||||
|
139 -> G3-Win
|
||||||
|
140 -> G3-Win
|
||||||
|
141 -> G3-Win
|
||||||
|
142 -> G3-Win
|
||||||
|
143 -> G3-Win
|
||||||
|
144 -> Honor
|
||||||
|
145 -> Honor
|
||||||
|
146 -> Honor
|
||||||
|
147 -> G1-Win
|
||||||
|
148 -> G1-Win
|
||||||
|
149 -> G2-Win
|
||||||
|
150 -> G3-Win
|
||||||
|
151 -> Honor
|
||||||
|
152 -> Honor
|
||||||
|
153 -> G1-Win
|
||||||
|
154 -> Honor
|
||||||
|
155 -> G1-Win
|
||||||
|
_ -> Honor
|
||||||
|
|
||||||
|
// Get the primary ID for a saddle.
|
||||||
|
// For saddles which are the primary version, or if no saddle matches the given ID,
|
||||||
|
// the result is the input.
|
||||||
|
pub fun primary(s: saddle-id): saddle-id
|
||||||
|
match s.game-id
|
||||||
|
144 -> Saddle-id(1)
|
||||||
|
145 -> Saddle-id(4)
|
||||||
|
146 -> Saddle-id(6)
|
||||||
|
147 -> Saddle-id(14)
|
||||||
|
148 -> Saddle-id(16)
|
||||||
|
149 -> Saddle-id(49)
|
||||||
|
151 -> Saddle-id(4)
|
||||||
|
152 -> Saddle-id(5)
|
||||||
|
153 -> Saddle-id(13)
|
||||||
|
154 -> Saddle-id(1)
|
||||||
|
155 -> Saddle-id(18)
|
||||||
|
_ -> s
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
17500
horse/global/skill.kk
17500
horse/global/skill.kk
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
module horse/legacy
|
module horse/legacy
|
||||||
|
|
||||||
import horse/character
|
import horse/character
|
||||||
|
import horse/game-id
|
||||||
import horse/race
|
import horse/race
|
||||||
import horse/spark
|
import horse/spark
|
||||||
|
|
||||||
@@ -9,9 +10,9 @@ pub struct legacy
|
|||||||
parents: (veteran, veteran)
|
parents: (veteran, veteran)
|
||||||
|
|
||||||
pub struct veteran
|
pub struct veteran
|
||||||
character: character
|
character: character-id
|
||||||
stat: spark<stat>
|
stat: spark<stat>
|
||||||
aptitude: spark<aptitude>
|
aptitude: spark<aptitude>
|
||||||
unique: maybe<spark<unique>>
|
unique: maybe<spark<unique>>
|
||||||
generic: list<spark<generic>>
|
generic: list<spark<generic>>
|
||||||
results: list<race-result>
|
saddles: list<saddle-id>
|
||||||
|
|||||||
104
horse/movement.kk
Normal file
104
horse/movement.kk
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
module horse/movement
|
||||||
|
|
||||||
|
// Running styles.
|
||||||
|
pub type style
|
||||||
|
Front-Runner
|
||||||
|
Pace-Chaser
|
||||||
|
Late-Surger
|
||||||
|
End-Closer
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Equality comparison of the `style` type.
|
||||||
|
pub fun style/(==)(this : style, other : style) : e bool
|
||||||
|
match (this, other)
|
||||||
|
(Front-Runner, Front-Runner) -> True
|
||||||
|
(Pace-Chaser, Pace-Chaser) -> True
|
||||||
|
(Late-Surger, Late-Surger) -> True
|
||||||
|
(End-Closer, End-Closer) -> True
|
||||||
|
(_, _) -> False
|
||||||
|
|
||||||
|
// Shows a string representation of the `style` type.
|
||||||
|
pub fun style/show(this : style) : e string
|
||||||
|
match this
|
||||||
|
Front-Runner -> "Front Runner"
|
||||||
|
Pace-Chaser -> "Pace Chaser"
|
||||||
|
Late-Surger -> "Late Surger"
|
||||||
|
End-Closer -> "End Closer"
|
||||||
|
|
||||||
|
// Starting aptitude levels.
|
||||||
|
pub type level
|
||||||
|
G
|
||||||
|
F
|
||||||
|
E
|
||||||
|
D
|
||||||
|
C
|
||||||
|
B
|
||||||
|
A
|
||||||
|
S
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Comparison of the `level` type.
|
||||||
|
pub fun level/cmp(this : level, other : level) : e order
|
||||||
|
match (this, other)
|
||||||
|
(G, G) -> Eq
|
||||||
|
(G, _) -> Lt
|
||||||
|
(_, G) -> Gt
|
||||||
|
(F, F) -> Eq
|
||||||
|
(F, _) -> Lt
|
||||||
|
(_, F) -> Gt
|
||||||
|
(E, E) -> Eq
|
||||||
|
(E, _) -> Lt
|
||||||
|
(_, E) -> Gt
|
||||||
|
(D, D) -> Eq
|
||||||
|
(D, _) -> Lt
|
||||||
|
(_, D) -> Gt
|
||||||
|
(C, C) -> Eq
|
||||||
|
(C, _) -> Lt
|
||||||
|
(_, C) -> Gt
|
||||||
|
(B, B) -> Eq
|
||||||
|
(B, _) -> Lt
|
||||||
|
(_, B) -> Gt
|
||||||
|
(A, A) -> Eq
|
||||||
|
(A, _) -> Lt
|
||||||
|
(_, A) -> Gt
|
||||||
|
(S, S) -> Eq
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Fip comparison of the `level` type.
|
||||||
|
pub fun level/order2(this : level, other : level) : order2<level>
|
||||||
|
match (this, other)
|
||||||
|
(G, G) -> Eq2(G)
|
||||||
|
(G, other') -> Lt2(G, other')
|
||||||
|
(this', G) -> Gt2(G, this')
|
||||||
|
(F, F) -> Eq2(F)
|
||||||
|
(F, other') -> Lt2(F, other')
|
||||||
|
(this', F) -> Gt2(F, this')
|
||||||
|
(E, E) -> Eq2(E)
|
||||||
|
(E, other') -> Lt2(E, other')
|
||||||
|
(this', E) -> Gt2(E, this')
|
||||||
|
(D, D) -> Eq2(D)
|
||||||
|
(D, other') -> Lt2(D, other')
|
||||||
|
(this', D) -> Gt2(D, this')
|
||||||
|
(C, C) -> Eq2(C)
|
||||||
|
(C, other') -> Lt2(C, other')
|
||||||
|
(this', C) -> Gt2(C, this')
|
||||||
|
(B, B) -> Eq2(B)
|
||||||
|
(B, other') -> Lt2(B, other')
|
||||||
|
(this', B) -> Gt2(B, this')
|
||||||
|
(A, A) -> Eq2(A)
|
||||||
|
(A, other') -> Lt2(A, other')
|
||||||
|
(this', A) -> Gt2(A, this')
|
||||||
|
(S, S) -> Eq2(S)
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Shows a string representation of the `level` type.
|
||||||
|
pub fun level/show(this : level) : string
|
||||||
|
match this
|
||||||
|
G -> "G"
|
||||||
|
F -> "F"
|
||||||
|
E -> "E"
|
||||||
|
D -> "D"
|
||||||
|
C -> "C"
|
||||||
|
B -> "B"
|
||||||
|
A -> "A"
|
||||||
|
S -> "S"
|
||||||
158
horse/prob/kfl.kk
Normal file
158
horse/prob/kfl.kk
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
module horse/prob/kfl
|
||||||
|
|
||||||
|
// kfl is a semiring of probabilities formed by vibes.
|
||||||
|
pub type kfl
|
||||||
|
// Effectively if not literally impossible events.
|
||||||
|
Impossible
|
||||||
|
// Not worth aiming for, but can technically still happen.
|
||||||
|
Probably-Not
|
||||||
|
// You expect it not to happen most of the time, but it might still be worth
|
||||||
|
// trying for it if you're being forced to play to your outs.
|
||||||
|
Doubtful
|
||||||
|
// More likely that it won't happen, but a success isn't surprising.
|
||||||
|
Unlikely
|
||||||
|
// Either it does or it doesn't.
|
||||||
|
Mayhapsibly
|
||||||
|
// Decent chance it doesn't happen, but you still expect it to.
|
||||||
|
Probably
|
||||||
|
// You expect it to happen most of the time, but accept that there will be failures.
|
||||||
|
Most-Likely
|
||||||
|
// Very close to guaranteed, but technically with a small chance to fail.
|
||||||
|
Cry-If-Not
|
||||||
|
// Absolutely guaranteed events.
|
||||||
|
Guaranteed
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Comparison of the `kfl` type.
|
||||||
|
pub fun cmp(this : kfl, other : kfl) : e order
|
||||||
|
match (this, other)
|
||||||
|
(Impossible, Impossible) -> Eq
|
||||||
|
(Impossible, _) -> Lt
|
||||||
|
(_, Impossible) -> Gt
|
||||||
|
(Probably-Not, Probably-Not) -> Eq
|
||||||
|
(Probably-Not, _) -> Lt
|
||||||
|
(_, Probably-Not) -> Gt
|
||||||
|
(Doubtful, Doubtful) -> Eq
|
||||||
|
(Doubtful, _) -> Lt
|
||||||
|
(_, Doubtful) -> Gt
|
||||||
|
(Unlikely, Unlikely) -> Eq
|
||||||
|
(Unlikely, _) -> Lt
|
||||||
|
(_, Unlikely) -> Gt
|
||||||
|
(Mayhapsibly, Mayhapsibly) -> Eq
|
||||||
|
(Mayhapsibly, _) -> Lt
|
||||||
|
(_, Mayhapsibly) -> Gt
|
||||||
|
(Probably, Probably) -> Eq
|
||||||
|
(Probably, _) -> Lt
|
||||||
|
(_, Probably) -> Gt
|
||||||
|
(Most-Likely, Most-Likely) -> Eq
|
||||||
|
(Most-Likely, _) -> Lt
|
||||||
|
(_, Most-Likely) -> Gt
|
||||||
|
(Cry-If-Not, Cry-If-Not) -> Eq
|
||||||
|
(Cry-If-Not, _) -> Lt
|
||||||
|
(_, Cry-If-Not) -> Gt
|
||||||
|
(Guaranteed, Guaranteed) -> Eq
|
||||||
|
|
||||||
|
// Shows a string representation of the `kfl` type.
|
||||||
|
pub fun show(this : kfl) : e string
|
||||||
|
match this
|
||||||
|
Impossible -> "impossible"
|
||||||
|
Probably-Not -> "probably not"
|
||||||
|
Doubtful -> "doubtful"
|
||||||
|
Unlikely -> "unlikely"
|
||||||
|
Mayhapsibly -> "mayhapsibly"
|
||||||
|
Probably -> "probably"
|
||||||
|
Most-Likely -> "most likely"
|
||||||
|
Cry-If-Not -> "cry if not"
|
||||||
|
Guaranteed -> "guaranteed"
|
||||||
|
|
||||||
|
// KFL multiplication, or the probability of cooccurrence of two independent events.
|
||||||
|
pub fun (*)(a: kfl, b: kfl): e kfl
|
||||||
|
val (l, h) = match a.cmp(b) // this operation is commutative
|
||||||
|
Gt -> (b, a)
|
||||||
|
_ -> (a, b)
|
||||||
|
match (l, h)
|
||||||
|
(r, Guaranteed) -> r // factor out Guaranteed cases
|
||||||
|
(Impossible, _) -> Impossible
|
||||||
|
(Probably-Not, _) -> Impossible
|
||||||
|
(r, Cry-If-Not) -> r // factor out further Cry-If-Not cases
|
||||||
|
(Doubtful, Most-Likely) -> Probably-Not
|
||||||
|
(Doubtful, _) -> Impossible
|
||||||
|
(Unlikely, Most-Likely) -> Doubtful
|
||||||
|
(Unlikely, Probably) -> Doubtful
|
||||||
|
(Unlikely, Mayhapsibly) -> Probably-Not
|
||||||
|
(Unlikely, _) -> Probably-Not // (Unlikely, Unlikely) because commutative
|
||||||
|
(Mayhapsibly, Most-Likely) -> Unlikely
|
||||||
|
(Mayhapsibly, Probably) -> Unlikely
|
||||||
|
(Mayhapsibly, _) -> Unlikely
|
||||||
|
(Probably, Most-Likely) -> Mayhapsibly
|
||||||
|
(Probably, _) -> Unlikely
|
||||||
|
(Most-Likely, _) -> Probably
|
||||||
|
// These two are only needed because the type system doesn't understand commutativity.
|
||||||
|
(Cry-If-Not, _) -> Cry-If-Not
|
||||||
|
(Guaranteed, _) -> Guaranteed
|
||||||
|
|
||||||
|
// KFL addition, or the probability of occurrence of at least one of two independent events.
|
||||||
|
pub fun (+)(a: kfl, b: kfl): e kfl
|
||||||
|
val (l, h) = match a.cmp(b) // this operation is commutative
|
||||||
|
Gt -> (b, a)
|
||||||
|
_ -> (a, b)
|
||||||
|
match (l, h)
|
||||||
|
// Cases with _ on the right are (a, a) due to commutativity.
|
||||||
|
// Cases with _ on the left simplify later cases that all absorb to the right.
|
||||||
|
(Guaranteed, _) -> Guaranteed
|
||||||
|
(_, Guaranteed) -> Guaranteed
|
||||||
|
(Cry-If-Not, _) -> Guaranteed
|
||||||
|
(Most-Likely, Cry-If-Not) -> Cry-If-Not
|
||||||
|
(Most-Likely, _) -> Cry-If-Not
|
||||||
|
(_, Cry-If-Not) -> Cry-If-Not
|
||||||
|
(Probably, Most-Likely) -> Cry-If-Not
|
||||||
|
(Probably, _) -> Most-Likely
|
||||||
|
(_, Most-Likely) -> Most-Likely
|
||||||
|
(Mayhapsibly, Probably) -> Most-Likely
|
||||||
|
(Mayhapsibly, _) -> Probably
|
||||||
|
(Unlikely, Probably) -> Most-Likely
|
||||||
|
(Unlikely, Mayhapsibly) -> Probably
|
||||||
|
(Unlikely, _) -> Mayhapsibly
|
||||||
|
(_, Probably) -> Probably
|
||||||
|
(Doubtful, Mayhapsibly) -> Probably
|
||||||
|
(Doubtful, Unlikely) -> Mayhapsibly
|
||||||
|
(Doubtful, _) -> Unlikely
|
||||||
|
(_, Mayhapsibly) -> Mayhapsibly
|
||||||
|
(_, Unlikely) -> Unlikely
|
||||||
|
(Probably-Not, Doubtful) -> Unlikely
|
||||||
|
(Probably-Not, _) -> Probably-Not
|
||||||
|
(_, Doubtful) -> Doubtful
|
||||||
|
(_, Probably-Not) -> Probably-Not
|
||||||
|
(_, Impossible) -> Impossible
|
||||||
|
|
||||||
|
// KFL union, or the probability of occurrence of exactly one of two independent events.
|
||||||
|
pub fun either(a: kfl, b: kfl): e kfl
|
||||||
|
val (l, h) = match a.cmp(b) // this operation is commutative
|
||||||
|
Gt -> (b, a)
|
||||||
|
_ -> (a, b)
|
||||||
|
match (l, h)
|
||||||
|
(Impossible, r) -> r
|
||||||
|
(Probably-Not, Guaranteed) -> Cry-If-Not
|
||||||
|
(Probably-Not, r) -> r
|
||||||
|
(Doubtful, Guaranteed) -> Most-Likely
|
||||||
|
(Doubtful, Cry-If-Not) -> Most-Likely
|
||||||
|
(Doubtful, Most-Likely) -> Probably
|
||||||
|
(Doubtful, Probably) -> Mayhapsibly
|
||||||
|
(Doubtful, Mayhapsibly) -> Mayhapsibly
|
||||||
|
(Doubtful, Unlikely) -> Mayhapsibly
|
||||||
|
(Doubtful, _) -> Unlikely
|
||||||
|
(Unlikely, Guaranteed) -> Probably
|
||||||
|
(Unlikely, Cry-If-Not) -> Mayhapsibly
|
||||||
|
(Unlikely, Most-Likely) -> Mayhapsibly
|
||||||
|
(Unlikely, _) -> Probably
|
||||||
|
(Mayhapsibly, Guaranteed) -> Mayhapsibly
|
||||||
|
(Mayhapsibly, Cry-If-Not) -> Mayhapsibly
|
||||||
|
(Mayhapsibly, Most-Likely) -> Mayhapsibly
|
||||||
|
(Mayhapsibly, _) -> Probably
|
||||||
|
(Probably, Guaranteed) -> Unlikely
|
||||||
|
(Probably, Cry-If-Not) -> Unlikely
|
||||||
|
(Probably, Most-Likely) -> Unlikely
|
||||||
|
(Probably, _) -> Mayhapsibly
|
||||||
|
(Most-Likely, _) -> Doubtful
|
||||||
|
(Cry-If-Not, _) -> Probably-Not
|
||||||
|
(Guaranteed, _) -> Impossible
|
||||||
58
horse/prob/pmf.kk
Normal file
58
horse/prob/pmf.kk
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
module horse/prob/pmf
|
||||||
|
|
||||||
|
import std/core/list
|
||||||
|
|
||||||
|
// Discrete-support probability distribution implemented as a list with the invariant
|
||||||
|
// that support is always given in increasing order.
|
||||||
|
pub type pmf<s, v>
|
||||||
|
Event(s: s, v: v, next: pmf<s, v>)
|
||||||
|
End
|
||||||
|
|
||||||
|
// Add an independent event to the distribution.
|
||||||
|
pub fun add(p: pmf<s, v>, s: s, v: v, ?s/cmp: (a: s, b: s) -> order, ?v/(+): (new: v, old: v) -> e v): e pmf<s, v>
|
||||||
|
match p
|
||||||
|
End -> Event(s, v, End)
|
||||||
|
Event(s', v', next) -> match s.cmp(s')
|
||||||
|
Lt -> Event(s, v, Event(s', v', next))
|
||||||
|
Eq -> Event(s, v + v', next)
|
||||||
|
Gt -> Event(s', v', add(next, s, v))
|
||||||
|
|
||||||
|
// Replace an event in the distribution.
|
||||||
|
pub inline fun set(p: pmf<s, v>, s: s, v: v, ?s/cmp: (a: s, b: s) -> order): e pmf<s, v>
|
||||||
|
p.add(s, v, cmp, fn(new, old) new)
|
||||||
|
|
||||||
|
// Construct a pmf from a list of (support, value) entries.
|
||||||
|
pub fun list/pmf(l: list<(s, v)>, ?s/cmp: (a: s, b: s) -> order, ?v/(+): (new: v, old: v) -> e v): e pmf<s, v>
|
||||||
|
l.foldl(End) fn(p, (s, v)) p.add(s, v)
|
||||||
|
|
||||||
|
// Fold over the entries of the distribution.
|
||||||
|
pub tail fun foldl(p: pmf<s, v>, init: a, f: (a, s, v) -> e a): e a
|
||||||
|
match p
|
||||||
|
End -> init
|
||||||
|
Event(s, v, next) -> foldl(next, f(init, s, v), f)
|
||||||
|
|
||||||
|
// Convert the distribution to a list of entries.
|
||||||
|
pub fun pmf/list(p: pmf<s, v>): list<(s, v)>
|
||||||
|
p.foldl(Nil) fn(l, s, v) Cons((s, v), l)
|
||||||
|
|
||||||
|
// Distribution of cooccurrence of two events described by their distributions.
|
||||||
|
pub fun (*)(a: pmf<s, v>, b: pmf<s, v>, ?s/cmp: (a: s, b: s) -> order, ?v/(*): (a: v, b: v) -> e v): e pmf<s, v>
|
||||||
|
match a
|
||||||
|
End -> End
|
||||||
|
Event(sa, va, nexta) -> match b
|
||||||
|
End -> End
|
||||||
|
Event(sb, vb, nextb) -> match sa.cmp(sb)
|
||||||
|
Lt -> nexta * b
|
||||||
|
Eq -> Event(sa, va * vb, nexta * nextb)
|
||||||
|
Gt -> a * nextb
|
||||||
|
|
||||||
|
// Distribution of occurrence of at least one of two events described by their distributions.
|
||||||
|
pub fun (+)(a: pmf<s, v>, b: pmf<s, v>, ?s/cmp: (a: s, b: s) -> order, ?v/(+): (a: v, b: v) -> e v): e pmf<s, v>
|
||||||
|
match a
|
||||||
|
End -> b
|
||||||
|
Event(sa, va, nexta) -> match b
|
||||||
|
End -> a
|
||||||
|
Event(sb, vb, nextb) -> match sa.cmp(sb)
|
||||||
|
Lt -> Event(sa, va, nexta + b)
|
||||||
|
Eq -> Event(sa, va + vb, nexta + nextb)
|
||||||
|
Gt -> Event(sb, vb, a + nextb)
|
||||||
37
horse/race.go
Normal file
37
horse/race.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package horse
|
||||||
|
|
||||||
|
type RaceID int32
|
||||||
|
|
||||||
|
// Race is the internal data about a race.
|
||||||
|
type Race struct {
|
||||||
|
ID RaceID
|
||||||
|
Name string
|
||||||
|
Thumbnail int
|
||||||
|
// Some careers contain unusual versions of races, e.g. Tenno Sho (Spring)
|
||||||
|
// in Hanshin instead of Kyoto for Narita Taishin and Biwa Hayahide.
|
||||||
|
// For such races, this field holds the normal race ID.
|
||||||
|
Primary RaceID
|
||||||
|
}
|
||||||
|
|
||||||
|
type SaddleID int32
|
||||||
|
|
||||||
|
// Saddle is the internal data about a race win saddle.
|
||||||
|
type Saddle struct {
|
||||||
|
ID SaddleID
|
||||||
|
Name string
|
||||||
|
Races []RaceID
|
||||||
|
Type SaddleType
|
||||||
|
// Saddles that involve alternate races are themselves alternate.
|
||||||
|
// For such saddles, this field holds the normal saddle ID.
|
||||||
|
Primary SaddleID
|
||||||
|
}
|
||||||
|
|
||||||
|
type SaddleType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Saddle for multiple race wins, e.g. Classic Triple Crown, Dual Grand Prix, &c.
|
||||||
|
SaddleTypeHonor SaddleType = iota
|
||||||
|
SaddleTypeG3
|
||||||
|
SaddleTypeG2
|
||||||
|
SaddleTypeG1
|
||||||
|
)
|
||||||
752
horse/race.kk
752
horse/race.kk
@@ -1,426 +1,30 @@
|
|||||||
module horse/race
|
module horse/race
|
||||||
|
|
||||||
import std/data/linearset
|
import std/data/linearset
|
||||||
|
import horse/game-id
|
||||||
|
|
||||||
// Exhaustive enumeration of graded races that can be run in career.
|
pub struct race-detail
|
||||||
// Races that can be run in multiple years are listed only once.
|
race-id: race-id
|
||||||
pub type career-race
|
name: string
|
||||||
February-Stakes
|
grade: grade
|
||||||
Takamatsunomiya-Kinen
|
thumbnail-id: race-thumbnail-id
|
||||||
Osaka-Hai
|
// Some careers contain unusual versions of races, e.g. Tenno Sho (Spring)
|
||||||
Oka-Sho
|
// in Hanshin instead of Kyoto for Narita Taishin and Biwa Hayahide.
|
||||||
Satsuki-Sho
|
// For such races, this field holds the normal race ID.
|
||||||
Tenno-Sho-Spring
|
primary: race-id
|
||||||
NHK-Mile-Cup
|
|
||||||
Victoria-Mile
|
|
||||||
Japanese-Oaks
|
|
||||||
Japanese-Derby
|
|
||||||
Yasuda-Kinen
|
|
||||||
Takarazuka-Kinen
|
|
||||||
Sprinters-Stakes
|
|
||||||
Shuka-Sho
|
|
||||||
Kikuka-Sho
|
|
||||||
Tenno-Sho-Autumn
|
|
||||||
Queen-Elizabeth-II-Cup
|
|
||||||
Mile-Championship
|
|
||||||
Japan-Cup
|
|
||||||
Champions-Cup
|
|
||||||
Hanshin-Juvenile-Fillies
|
|
||||||
Asahi-Hai-Futurity-Stakes
|
|
||||||
Arima-Kinen
|
|
||||||
Hopeful-Stakes
|
|
||||||
Tokyo-Daishoten
|
|
||||||
JBC-Classic
|
|
||||||
JBC-Sprint
|
|
||||||
JBC-Ladies-Classic
|
|
||||||
Japan-Dirt-Derby
|
|
||||||
Teio-Sho
|
|
||||||
Nikkei-Shinshun-Hai
|
|
||||||
Tokai-Stakes
|
|
||||||
American-Jockey-Club-Cup
|
|
||||||
Kyoto-Kinen
|
|
||||||
Nakayama-Kinen
|
|
||||||
Tulip-Sho
|
|
||||||
Yayoi-Sho
|
|
||||||
Kinko-Sho
|
|
||||||
Fillies-Revue
|
|
||||||
Hanshin-Daishoten
|
|
||||||
Spring-Stakes
|
|
||||||
Nikkei-Sho
|
|
||||||
Hanshin-Umamusume-Stakes
|
|
||||||
New-Zealand-Trophy
|
|
||||||
Yomiuri-Milers-Cup
|
|
||||||
Flora-Stakes
|
|
||||||
Aoba-Sho
|
|
||||||
Kyoto-Shimbun-Hai
|
|
||||||
Keio-Hai-Spring-Cup
|
|
||||||
Meguro-Kinen
|
|
||||||
Sapporo-Kinen
|
|
||||||
Centaur-Stakes
|
|
||||||
Rose-Stakes
|
|
||||||
St-Lite-Kinen
|
|
||||||
Kobe-Shimbun-Hai
|
|
||||||
All-Comers
|
|
||||||
Mainichi-Okan
|
|
||||||
Kyoto-Daishoten
|
|
||||||
Fuchu-Umamusume-Stakes
|
|
||||||
Fuji-Stakes
|
|
||||||
Swan-Stakes
|
|
||||||
Keio-Hai-Junior-Stakes
|
|
||||||
Copa-Republica-Argentina
|
|
||||||
Daily-Hai-Junior-Stakes
|
|
||||||
Stayers-Stakes
|
|
||||||
Hanshin-Cup
|
|
||||||
Kyoto-Kimpai
|
|
||||||
Nakayama-Kimpai
|
|
||||||
Shinzan-Kinen
|
|
||||||
Fairy-Stakes
|
|
||||||
Aichi-Hai
|
|
||||||
Keisei-Hai
|
|
||||||
Silk-Road-Stakes
|
|
||||||
Negishi-Stakes
|
|
||||||
Kisaragi-Sho
|
|
||||||
Tokyo-Shimbun-Hai
|
|
||||||
Queen-Cup
|
|
||||||
Kyodo-News-Hai
|
|
||||||
Kyoto-Umamusume-Stakes
|
|
||||||
Diamond-Stakes
|
|
||||||
Kokura-Daishoten
|
|
||||||
Arlington-Cup
|
|
||||||
Hankyu-Hai
|
|
||||||
Ocean-Stakes
|
|
||||||
Nakayama-Umamusume-Stakes
|
|
||||||
Falcon-Stakes
|
|
||||||
Flower-Cup
|
|
||||||
Mainichi-Hai
|
|
||||||
March-Stakes
|
|
||||||
Lord-Derby-Challenge-Trophy
|
|
||||||
Antares-Stakes
|
|
||||||
Fukushima-Umamusume-Stakes
|
|
||||||
Niigata-Daishoten
|
|
||||||
Heian-Stakes
|
|
||||||
Aoi-Stakes
|
|
||||||
Naruo-Kinen
|
|
||||||
Mermaid-Stakes
|
|
||||||
Epsom-Cup
|
|
||||||
Unicorn-Stakes
|
|
||||||
Hakodate-Sprint-Stakes
|
|
||||||
CBC-Sho
|
|
||||||
Radio-Nikkei-Sho
|
|
||||||
Procyon-Stakes
|
|
||||||
Tanabata-Sho
|
|
||||||
Hakodate-Kinen
|
|
||||||
Chukyo-Kinen
|
|
||||||
Hakodate-Junior-Stakes
|
|
||||||
Ibis-Summer-Dash
|
|
||||||
Queen-Stakes
|
|
||||||
Kokura-Kinen
|
|
||||||
Leopard-Stakes
|
|
||||||
Sekiya-Kinen
|
|
||||||
Elm-Stakes
|
|
||||||
Kitakyushu-Kinen
|
|
||||||
Niigata-Junior-Stakes
|
|
||||||
Keeneland-Cup
|
|
||||||
Sapporo-Junior-Stakes
|
|
||||||
Kokura-Junior-Stakes
|
|
||||||
Niigata-Kinen
|
|
||||||
Shion-Stakes
|
|
||||||
Keisei-Hai-Autumn-Handicap
|
|
||||||
Sirius-Stakes
|
|
||||||
Saudi-Arabia-Royal-Cup
|
|
||||||
Artemis-Stakes
|
|
||||||
Fantasy-Stakes
|
|
||||||
Miyako-Stakes
|
|
||||||
Musashino-Stakes
|
|
||||||
Fukushima-Kinen
|
|
||||||
Tokyo-Sports-Hai-Junior-Stakes
|
|
||||||
Kyoto-Junior-Stakes
|
|
||||||
Keihan-Hai
|
|
||||||
Challenge-Cup
|
|
||||||
Chunichi-Shimbun-Hai
|
|
||||||
Capella-Stakes
|
|
||||||
Turquoise-Stakes
|
|
||||||
|
|
||||||
// Automatically generated.
|
pub fun detail(
|
||||||
// Shows a string representation of the `career-race` type.
|
r: race-id,
|
||||||
pub fun career-race/show(this : career-race) : e string
|
?race/show: (race-id) -> string,
|
||||||
match this
|
?race/grade: (race-id) -> grade,
|
||||||
February-Stakes -> "February Stakes"
|
?race/thumbnail: (race-id) -> race-thumbnail-id,
|
||||||
Takamatsunomiya-Kinen -> "Takamatsunomiya Kinen"
|
?race/primary: (race-id) -> race-id
|
||||||
Osaka-Hai -> "Osaka Hai"
|
): race-detail
|
||||||
Oka-Sho -> "Oka Sho"
|
Race-detail(r, r.show, r.grade, r.thumbnail, r.primary)
|
||||||
Satsuki-Sho -> "Satsuki Sho"
|
|
||||||
Tenno-Sho-Spring -> "Tenno Sho Spring"
|
|
||||||
NHK-Mile-Cup -> "NHK Mile Cup"
|
|
||||||
Victoria-Mile -> "Victoria Mile"
|
|
||||||
Japanese-Oaks -> "Japanese Oaks"
|
|
||||||
Japanese-Derby -> "Japanese Derby"
|
|
||||||
Yasuda-Kinen -> "Yasuda Kinen"
|
|
||||||
Takarazuka-Kinen -> "Takarazuka Kinen"
|
|
||||||
Sprinters-Stakes -> "Sprinters Stakes"
|
|
||||||
Shuka-Sho -> "Shuka Sho"
|
|
||||||
Kikuka-Sho -> "Kikuka Sho"
|
|
||||||
Tenno-Sho-Autumn -> "Tenno Sho Autumn"
|
|
||||||
Queen-Elizabeth-II-Cup -> "Queen Elizabeth II Cup"
|
|
||||||
Mile-Championship -> "Mile Championship"
|
|
||||||
Japan-Cup -> "Japan Cup"
|
|
||||||
Champions-Cup -> "Champions Cup"
|
|
||||||
Hanshin-Juvenile-Fillies -> "Hanshin Juvenile Fillies"
|
|
||||||
Asahi-Hai-Futurity-Stakes -> "Asahi Hai Futurity Stakes"
|
|
||||||
Arima-Kinen -> "Arima Kinen"
|
|
||||||
Hopeful-Stakes -> "Hopeful Stakes"
|
|
||||||
Tokyo-Daishoten -> "Tokyo Daishoten"
|
|
||||||
JBC-Classic -> "JBC Classic"
|
|
||||||
JBC-Sprint -> "JBC Sprint"
|
|
||||||
JBC-Ladies-Classic -> "JBC Ladies Classic"
|
|
||||||
Japan-Dirt-Derby -> "Japan Dirt Derby"
|
|
||||||
Teio-Sho -> "Teio Sho"
|
|
||||||
Nikkei-Shinshun-Hai -> "Nikkei Shinshun Hai"
|
|
||||||
Tokai-Stakes -> "Tokai Stakes"
|
|
||||||
American-Jockey-Club-Cup -> "American Jockey Club Cup"
|
|
||||||
Kyoto-Kinen -> "Kyoto Kinen"
|
|
||||||
Nakayama-Kinen -> "Nakayama Kinen"
|
|
||||||
Tulip-Sho -> "Tulip Sho"
|
|
||||||
Yayoi-Sho -> "Yayoi Sho"
|
|
||||||
Kinko-Sho -> "Kinko Sho"
|
|
||||||
Fillies-Revue -> "Fillies Revue"
|
|
||||||
Hanshin-Daishoten -> "Hanshin Daishoten"
|
|
||||||
Spring-Stakes -> "Spring Stakes"
|
|
||||||
Nikkei-Sho -> "Nikkei Sho"
|
|
||||||
Hanshin-Umamusume-Stakes -> "Hanshin Umamusume Stakes"
|
|
||||||
New-Zealand-Trophy -> "New Zealand Trophy"
|
|
||||||
Yomiuri-Milers-Cup -> "Yomiuri Milers Cup"
|
|
||||||
Flora-Stakes -> "Flora Stakes"
|
|
||||||
Aoba-Sho -> "Aoba Sho"
|
|
||||||
Kyoto-Shimbun-Hai -> "Kyoto Shimbun Hai"
|
|
||||||
Keio-Hai-Spring-Cup -> "Keio Hai Spring Cup"
|
|
||||||
Meguro-Kinen -> "Meguro Kinen"
|
|
||||||
Sapporo-Kinen -> "Sapporo Kinen"
|
|
||||||
Centaur-Stakes -> "Centaur Stakes"
|
|
||||||
Rose-Stakes -> "Rose Stakes"
|
|
||||||
St-Lite-Kinen -> "St Lite Kinen"
|
|
||||||
Kobe-Shimbun-Hai -> "Kobe Shimbun Hai"
|
|
||||||
All-Comers -> "All Comers"
|
|
||||||
Mainichi-Okan -> "Mainichi Okan"
|
|
||||||
Kyoto-Daishoten -> "Kyoto Daishoten"
|
|
||||||
Fuchu-Umamusume-Stakes -> "Fuchu Umamusume Stakes"
|
|
||||||
Fuji-Stakes -> "Fuji Stakes"
|
|
||||||
Swan-Stakes -> "Swan Stakes"
|
|
||||||
Keio-Hai-Junior-Stakes -> "Keio Hai Junior Stakes"
|
|
||||||
Copa-Republica-Argentina -> "Copa Republica Argentina"
|
|
||||||
Daily-Hai-Junior-Stakes -> "Daily Hai Junior Stakes"
|
|
||||||
Stayers-Stakes -> "Stayers Stakes"
|
|
||||||
Hanshin-Cup -> "Hanshin Cup"
|
|
||||||
Kyoto-Kimpai -> "Kyoto Kimpai"
|
|
||||||
Nakayama-Kimpai -> "Nakayama Kimpai"
|
|
||||||
Shinzan-Kinen -> "Shinzan Kinen"
|
|
||||||
Fairy-Stakes -> "Fairy Stakes"
|
|
||||||
Aichi-Hai -> "Aichi Hai"
|
|
||||||
Keisei-Hai -> "Keisei Hai"
|
|
||||||
Silk-Road-Stakes -> "Silk Road Stakes"
|
|
||||||
Negishi-Stakes -> "Negishi Stakes"
|
|
||||||
Kisaragi-Sho -> "Kisaragi Sho"
|
|
||||||
Tokyo-Shimbun-Hai -> "Tokyo Shimbun Hai"
|
|
||||||
Queen-Cup -> "Queen Cup"
|
|
||||||
Kyodo-News-Hai -> "Kyodo News Hai"
|
|
||||||
Kyoto-Umamusume-Stakes -> "Kyoto Umamusume Stakes"
|
|
||||||
Diamond-Stakes -> "Diamond Stakes"
|
|
||||||
Kokura-Daishoten -> "Kokura Daishoten"
|
|
||||||
Arlington-Cup -> "Arlington Cup"
|
|
||||||
Hankyu-Hai -> "Hankyu Hai"
|
|
||||||
Ocean-Stakes -> "Ocean Stakes"
|
|
||||||
Nakayama-Umamusume-Stakes -> "Nakayama Umamusume Stakes"
|
|
||||||
Falcon-Stakes -> "Falcon Stakes"
|
|
||||||
Flower-Cup -> "Flower Cup"
|
|
||||||
Mainichi-Hai -> "Mainichi Hai"
|
|
||||||
March-Stakes -> "March Stakes"
|
|
||||||
Lord-Derby-Challenge-Trophy -> "Lord Derby Challenge Trophy"
|
|
||||||
Antares-Stakes -> "Antares Stakes"
|
|
||||||
Fukushima-Umamusume-Stakes -> "Fukushima Umamusume Stakes"
|
|
||||||
Niigata-Daishoten -> "Niigata Daishoten"
|
|
||||||
Heian-Stakes -> "Heian Stakes"
|
|
||||||
Aoi-Stakes -> "Aoi Stakes"
|
|
||||||
Naruo-Kinen -> "Naruo Kinen"
|
|
||||||
Mermaid-Stakes -> "Mermaid Stakes"
|
|
||||||
Epsom-Cup -> "Epsom Cup"
|
|
||||||
Unicorn-Stakes -> "Unicorn Stakes"
|
|
||||||
Hakodate-Sprint-Stakes -> "Hakodate Sprint Stakes"
|
|
||||||
CBC-Sho -> "CBC Sho"
|
|
||||||
Radio-Nikkei-Sho -> "Radio Nikkei Sho"
|
|
||||||
Procyon-Stakes -> "Procyon Stakes"
|
|
||||||
Tanabata-Sho -> "Tanabata Sho"
|
|
||||||
Hakodate-Kinen -> "Hakodate Kinen"
|
|
||||||
Chukyo-Kinen -> "Chukyo Kinen"
|
|
||||||
Hakodate-Junior-Stakes -> "Hakodate Junior Stakes"
|
|
||||||
Ibis-Summer-Dash -> "Ibis Summer Dash"
|
|
||||||
Queen-Stakes -> "Queen Stakes"
|
|
||||||
Kokura-Kinen -> "Kokura Kinen"
|
|
||||||
Leopard-Stakes -> "Leopard Stakes"
|
|
||||||
Sekiya-Kinen -> "Sekiya Kinen"
|
|
||||||
Elm-Stakes -> "Elm Stakes"
|
|
||||||
Kitakyushu-Kinen -> "Kitakyushu Kinen"
|
|
||||||
Niigata-Junior-Stakes -> "Niigata Junior Stakes"
|
|
||||||
Keeneland-Cup -> "Keeneland Cup"
|
|
||||||
Sapporo-Junior-Stakes -> "Sapporo Junior Stakes"
|
|
||||||
Kokura-Junior-Stakes -> "Kokura Junior Stakes"
|
|
||||||
Niigata-Kinen -> "Niigata Kinen"
|
|
||||||
Shion-Stakes -> "Shion Stakes"
|
|
||||||
Keisei-Hai-Autumn-Handicap -> "Keisei Hai Autumn Handicap"
|
|
||||||
Sirius-Stakes -> "Sirius Stakes"
|
|
||||||
Saudi-Arabia-Royal-Cup -> "Saudi Arabia Royal Cup"
|
|
||||||
Artemis-Stakes -> "Artemis Stakes"
|
|
||||||
Fantasy-Stakes -> "Fantasy Stakes"
|
|
||||||
Miyako-Stakes -> "Miyako Stakes"
|
|
||||||
Musashino-Stakes -> "Musashino Stakes"
|
|
||||||
Fukushima-Kinen -> "Fukushima Kinen"
|
|
||||||
Tokyo-Sports-Hai-Junior-Stakes -> "Tokyo Sports Hai Junior Stakes"
|
|
||||||
Kyoto-Junior-Stakes -> "Kyoto Junior Stakes"
|
|
||||||
Keihan-Hai -> "Keihan Hai"
|
|
||||||
Challenge-Cup -> "Challenge Cup"
|
|
||||||
Chunichi-Shimbun-Hai -> "Chunichi Shimbun Hai"
|
|
||||||
Capella-Stakes -> "Capella Stakes"
|
|
||||||
Turquoise-Stakes -> "Turquoise Stakes"
|
|
||||||
|
|
||||||
// Automatically generated.
|
pub fun race-detail/show(r: race-detail): string
|
||||||
// Equality comparison of the `career-race` type.
|
val Race-detail(Race-id(id), name) = r
|
||||||
pub fun career-race/(==)(this : career-race, other : career-race) : e bool
|
name ++ " (ID " ++ id.show ++ ")"
|
||||||
match (this, other)
|
|
||||||
(February-Stakes, February-Stakes) -> True
|
|
||||||
(Takamatsunomiya-Kinen, Takamatsunomiya-Kinen) -> True
|
|
||||||
(Osaka-Hai, Osaka-Hai) -> True
|
|
||||||
(Oka-Sho, Oka-Sho) -> True
|
|
||||||
(Satsuki-Sho, Satsuki-Sho) -> True
|
|
||||||
(Tenno-Sho-Spring, Tenno-Sho-Spring) -> True
|
|
||||||
(NHK-Mile-Cup, NHK-Mile-Cup) -> True
|
|
||||||
(Victoria-Mile, Victoria-Mile) -> True
|
|
||||||
(Japanese-Oaks, Japanese-Oaks) -> True
|
|
||||||
(Japanese-Derby, Japanese-Derby) -> True
|
|
||||||
(Yasuda-Kinen, Yasuda-Kinen) -> True
|
|
||||||
(Takarazuka-Kinen, Takarazuka-Kinen) -> True
|
|
||||||
(Sprinters-Stakes, Sprinters-Stakes) -> True
|
|
||||||
(Shuka-Sho, Shuka-Sho) -> True
|
|
||||||
(Kikuka-Sho, Kikuka-Sho) -> True
|
|
||||||
(Tenno-Sho-Autumn, Tenno-Sho-Autumn) -> True
|
|
||||||
(Queen-Elizabeth-II-Cup, Queen-Elizabeth-II-Cup) -> True
|
|
||||||
(Mile-Championship, Mile-Championship) -> True
|
|
||||||
(Japan-Cup, Japan-Cup) -> True
|
|
||||||
(Champions-Cup, Champions-Cup) -> True
|
|
||||||
(Hanshin-Juvenile-Fillies, Hanshin-Juvenile-Fillies) -> True
|
|
||||||
(Asahi-Hai-Futurity-Stakes, Asahi-Hai-Futurity-Stakes) -> True
|
|
||||||
(Arima-Kinen, Arima-Kinen) -> True
|
|
||||||
(Hopeful-Stakes, Hopeful-Stakes) -> True
|
|
||||||
(Tokyo-Daishoten, Tokyo-Daishoten) -> True
|
|
||||||
(JBC-Classic, JBC-Classic) -> True
|
|
||||||
(JBC-Sprint, JBC-Sprint) -> True
|
|
||||||
(JBC-Ladies-Classic, JBC-Ladies-Classic) -> True
|
|
||||||
(Japan-Dirt-Derby, Japan-Dirt-Derby) -> True
|
|
||||||
(Teio-Sho, Teio-Sho) -> True
|
|
||||||
(Nikkei-Shinshun-Hai, Nikkei-Shinshun-Hai) -> True
|
|
||||||
(Tokai-Stakes, Tokai-Stakes) -> True
|
|
||||||
(American-Jockey-Club-Cup, American-Jockey-Club-Cup) -> True
|
|
||||||
(Kyoto-Kinen, Kyoto-Kinen) -> True
|
|
||||||
(Nakayama-Kinen, Nakayama-Kinen) -> True
|
|
||||||
(Tulip-Sho, Tulip-Sho) -> True
|
|
||||||
(Yayoi-Sho, Yayoi-Sho) -> True
|
|
||||||
(Kinko-Sho, Kinko-Sho) -> True
|
|
||||||
(Fillies-Revue, Fillies-Revue) -> True
|
|
||||||
(Hanshin-Daishoten, Hanshin-Daishoten) -> True
|
|
||||||
(Spring-Stakes, Spring-Stakes) -> True
|
|
||||||
(Nikkei-Sho, Nikkei-Sho) -> True
|
|
||||||
(Hanshin-Umamusume-Stakes, Hanshin-Umamusume-Stakes) -> True
|
|
||||||
(New-Zealand-Trophy, New-Zealand-Trophy) -> True
|
|
||||||
(Yomiuri-Milers-Cup, Yomiuri-Milers-Cup) -> True
|
|
||||||
(Flora-Stakes, Flora-Stakes) -> True
|
|
||||||
(Aoba-Sho, Aoba-Sho) -> True
|
|
||||||
(Kyoto-Shimbun-Hai, Kyoto-Shimbun-Hai) -> True
|
|
||||||
(Keio-Hai-Spring-Cup, Keio-Hai-Spring-Cup) -> True
|
|
||||||
(Meguro-Kinen, Meguro-Kinen) -> True
|
|
||||||
(Sapporo-Kinen, Sapporo-Kinen) -> True
|
|
||||||
(Centaur-Stakes, Centaur-Stakes) -> True
|
|
||||||
(Rose-Stakes, Rose-Stakes) -> True
|
|
||||||
(St-Lite-Kinen, St-Lite-Kinen) -> True
|
|
||||||
(Kobe-Shimbun-Hai, Kobe-Shimbun-Hai) -> True
|
|
||||||
(All-Comers, All-Comers) -> True
|
|
||||||
(Mainichi-Okan, Mainichi-Okan) -> True
|
|
||||||
(Kyoto-Daishoten, Kyoto-Daishoten) -> True
|
|
||||||
(Fuchu-Umamusume-Stakes, Fuchu-Umamusume-Stakes) -> True
|
|
||||||
(Fuji-Stakes, Fuji-Stakes) -> True
|
|
||||||
(Swan-Stakes, Swan-Stakes) -> True
|
|
||||||
(Keio-Hai-Junior-Stakes, Keio-Hai-Junior-Stakes) -> True
|
|
||||||
(Copa-Republica-Argentina, Copa-Republica-Argentina) -> True
|
|
||||||
(Daily-Hai-Junior-Stakes, Daily-Hai-Junior-Stakes) -> True
|
|
||||||
(Stayers-Stakes, Stayers-Stakes) -> True
|
|
||||||
(Hanshin-Cup, Hanshin-Cup) -> True
|
|
||||||
(Kyoto-Kimpai, Kyoto-Kimpai) -> True
|
|
||||||
(Nakayama-Kimpai, Nakayama-Kimpai) -> True
|
|
||||||
(Shinzan-Kinen, Shinzan-Kinen) -> True
|
|
||||||
(Fairy-Stakes, Fairy-Stakes) -> True
|
|
||||||
(Aichi-Hai, Aichi-Hai) -> True
|
|
||||||
(Keisei-Hai, Keisei-Hai) -> True
|
|
||||||
(Silk-Road-Stakes, Silk-Road-Stakes) -> True
|
|
||||||
(Negishi-Stakes, Negishi-Stakes) -> True
|
|
||||||
(Kisaragi-Sho, Kisaragi-Sho) -> True
|
|
||||||
(Tokyo-Shimbun-Hai, Tokyo-Shimbun-Hai) -> True
|
|
||||||
(Queen-Cup, Queen-Cup) -> True
|
|
||||||
(Kyodo-News-Hai, Kyodo-News-Hai) -> True
|
|
||||||
(Kyoto-Umamusume-Stakes, Kyoto-Umamusume-Stakes) -> True
|
|
||||||
(Diamond-Stakes, Diamond-Stakes) -> True
|
|
||||||
(Kokura-Daishoten, Kokura-Daishoten) -> True
|
|
||||||
(Arlington-Cup, Arlington-Cup) -> True
|
|
||||||
(Hankyu-Hai, Hankyu-Hai) -> True
|
|
||||||
(Ocean-Stakes, Ocean-Stakes) -> True
|
|
||||||
(Nakayama-Umamusume-Stakes, Nakayama-Umamusume-Stakes) -> True
|
|
||||||
(Falcon-Stakes, Falcon-Stakes) -> True
|
|
||||||
(Flower-Cup, Flower-Cup) -> True
|
|
||||||
(Mainichi-Hai, Mainichi-Hai) -> True
|
|
||||||
(March-Stakes, March-Stakes) -> True
|
|
||||||
(Lord-Derby-Challenge-Trophy, Lord-Derby-Challenge-Trophy) -> True
|
|
||||||
(Antares-Stakes, Antares-Stakes) -> True
|
|
||||||
(Fukushima-Umamusume-Stakes, Fukushima-Umamusume-Stakes) -> True
|
|
||||||
(Niigata-Daishoten, Niigata-Daishoten) -> True
|
|
||||||
(Heian-Stakes, Heian-Stakes) -> True
|
|
||||||
(Aoi-Stakes, Aoi-Stakes) -> True
|
|
||||||
(Naruo-Kinen, Naruo-Kinen) -> True
|
|
||||||
(Mermaid-Stakes, Mermaid-Stakes) -> True
|
|
||||||
(Epsom-Cup, Epsom-Cup) -> True
|
|
||||||
(Unicorn-Stakes, Unicorn-Stakes) -> True
|
|
||||||
(Hakodate-Sprint-Stakes, Hakodate-Sprint-Stakes) -> True
|
|
||||||
(CBC-Sho, CBC-Sho) -> True
|
|
||||||
(Radio-Nikkei-Sho, Radio-Nikkei-Sho) -> True
|
|
||||||
(Procyon-Stakes, Procyon-Stakes) -> True
|
|
||||||
(Tanabata-Sho, Tanabata-Sho) -> True
|
|
||||||
(Hakodate-Kinen, Hakodate-Kinen) -> True
|
|
||||||
(Chukyo-Kinen, Chukyo-Kinen) -> True
|
|
||||||
(Hakodate-Junior-Stakes, Hakodate-Junior-Stakes) -> True
|
|
||||||
(Ibis-Summer-Dash, Ibis-Summer-Dash) -> True
|
|
||||||
(Queen-Stakes, Queen-Stakes) -> True
|
|
||||||
(Kokura-Kinen, Kokura-Kinen) -> True
|
|
||||||
(Leopard-Stakes, Leopard-Stakes) -> True
|
|
||||||
(Sekiya-Kinen, Sekiya-Kinen) -> True
|
|
||||||
(Elm-Stakes, Elm-Stakes) -> True
|
|
||||||
(Kitakyushu-Kinen, Kitakyushu-Kinen) -> True
|
|
||||||
(Niigata-Junior-Stakes, Niigata-Junior-Stakes) -> True
|
|
||||||
(Keeneland-Cup, Keeneland-Cup) -> True
|
|
||||||
(Sapporo-Junior-Stakes, Sapporo-Junior-Stakes) -> True
|
|
||||||
(Kokura-Junior-Stakes, Kokura-Junior-Stakes) -> True
|
|
||||||
(Niigata-Kinen, Niigata-Kinen) -> True
|
|
||||||
(Shion-Stakes, Shion-Stakes) -> True
|
|
||||||
(Keisei-Hai-Autumn-Handicap, Keisei-Hai-Autumn-Handicap) -> True
|
|
||||||
(Sirius-Stakes, Sirius-Stakes) -> True
|
|
||||||
(Saudi-Arabia-Royal-Cup, Saudi-Arabia-Royal-Cup) -> True
|
|
||||||
(Artemis-Stakes, Artemis-Stakes) -> True
|
|
||||||
(Fantasy-Stakes, Fantasy-Stakes) -> True
|
|
||||||
(Miyako-Stakes, Miyako-Stakes) -> True
|
|
||||||
(Musashino-Stakes, Musashino-Stakes) -> True
|
|
||||||
(Fukushima-Kinen, Fukushima-Kinen) -> True
|
|
||||||
(Tokyo-Sports-Hai-Junior-Stakes, Tokyo-Sports-Hai-Junior-Stakes) -> True
|
|
||||||
(Kyoto-Junior-Stakes, Kyoto-Junior-Stakes) -> True
|
|
||||||
(Keihan-Hai, Keihan-Hai) -> True
|
|
||||||
(Challenge-Cup, Challenge-Cup) -> True
|
|
||||||
(Chunichi-Shimbun-Hai, Chunichi-Shimbun-Hai) -> True
|
|
||||||
(Capella-Stakes, Capella-Stakes) -> True
|
|
||||||
(Turquoise-Stakes, Turquoise-Stakes) -> True
|
|
||||||
(_, _) -> False
|
|
||||||
|
|
||||||
// Race grades.
|
// Race grades.
|
||||||
pub type grade
|
pub type grade
|
||||||
@@ -431,250 +35,86 @@ pub type grade
|
|||||||
G1
|
G1
|
||||||
EX
|
EX
|
||||||
|
|
||||||
pub fun career-race/grade(r: career-race): grade
|
// Automatically generated.
|
||||||
match r
|
// Comparison of the `grade` type.
|
||||||
February-Stakes -> G1
|
pub fun grade/cmp(this : grade, other : grade) : e order
|
||||||
Takamatsunomiya-Kinen -> G1
|
match (this, other)
|
||||||
Osaka-Hai -> G1
|
(Pre-OP, Pre-OP) -> Eq
|
||||||
Oka-Sho -> G1
|
(Pre-OP, _) -> Lt
|
||||||
Satsuki-Sho -> G1
|
(_, Pre-OP) -> Gt
|
||||||
Tenno-Sho-Spring -> G1
|
(OP, OP) -> Eq
|
||||||
NHK-Mile-Cup -> G1
|
(OP, _) -> Lt
|
||||||
Victoria-Mile -> G1
|
(_, OP) -> Gt
|
||||||
Japanese-Oaks -> G1
|
(G3, G3) -> Eq
|
||||||
Japanese-Derby -> G1
|
(G3, _) -> Lt
|
||||||
Yasuda-Kinen -> G1
|
(_, G3) -> Gt
|
||||||
Takarazuka-Kinen -> G1
|
(G2, G2) -> Eq
|
||||||
Sprinters-Stakes -> G1
|
(G2, _) -> Lt
|
||||||
Shuka-Sho -> G1
|
(_, G2) -> Gt
|
||||||
Kikuka-Sho -> G1
|
(G1, G1) -> Eq
|
||||||
Tenno-Sho-Autumn -> G1
|
(G1, _) -> Lt
|
||||||
Queen-Elizabeth-II-Cup -> G1
|
(_, G1) -> Gt
|
||||||
Mile-Championship -> G1
|
(EX, EX) -> Eq
|
||||||
Japan-Cup -> G1
|
|
||||||
Champions-Cup -> G1
|
|
||||||
Hanshin-Juvenile-Fillies -> G1
|
|
||||||
Asahi-Hai-Futurity-Stakes -> G1
|
|
||||||
Arima-Kinen -> G1
|
|
||||||
Hopeful-Stakes -> G1
|
|
||||||
Tokyo-Daishoten -> G1
|
|
||||||
JBC-Classic -> G1
|
|
||||||
JBC-Sprint -> G1
|
|
||||||
JBC-Ladies-Classic -> G1
|
|
||||||
Japan-Dirt-Derby -> G1
|
|
||||||
Teio-Sho -> G1
|
|
||||||
Nikkei-Shinshun-Hai -> G2
|
|
||||||
Tokai-Stakes -> G2
|
|
||||||
American-Jockey-Club-Cup -> G2
|
|
||||||
Kyoto-Kinen -> G2
|
|
||||||
Nakayama-Kinen -> G2
|
|
||||||
Tulip-Sho -> G2
|
|
||||||
Yayoi-Sho -> G2
|
|
||||||
Kinko-Sho -> G2
|
|
||||||
Fillies-Revue -> G2
|
|
||||||
Hanshin-Daishoten -> G2
|
|
||||||
Spring-Stakes -> G2
|
|
||||||
Nikkei-Sho -> G2
|
|
||||||
Hanshin-Umamusume-Stakes -> G2
|
|
||||||
New-Zealand-Trophy -> G2
|
|
||||||
Yomiuri-Milers-Cup -> G2
|
|
||||||
Flora-Stakes -> G2
|
|
||||||
Aoba-Sho -> G2
|
|
||||||
Kyoto-Shimbun-Hai -> G2
|
|
||||||
Keio-Hai-Spring-Cup -> G2
|
|
||||||
Meguro-Kinen -> G2
|
|
||||||
Sapporo-Kinen -> G2
|
|
||||||
Centaur-Stakes -> G2
|
|
||||||
Rose-Stakes -> G2
|
|
||||||
St-Lite-Kinen -> G2
|
|
||||||
Kobe-Shimbun-Hai -> G2
|
|
||||||
All-Comers -> G2
|
|
||||||
Mainichi-Okan -> G2
|
|
||||||
Kyoto-Daishoten -> G2
|
|
||||||
Fuchu-Umamusume-Stakes -> G2
|
|
||||||
Fuji-Stakes -> G2
|
|
||||||
Swan-Stakes -> G2
|
|
||||||
Keio-Hai-Junior-Stakes -> G2
|
|
||||||
Copa-Republica-Argentina -> G2
|
|
||||||
Daily-Hai-Junior-Stakes -> G2
|
|
||||||
Stayers-Stakes -> G2
|
|
||||||
Hanshin-Cup -> G2
|
|
||||||
Kyoto-Kimpai -> G3
|
|
||||||
Nakayama-Kimpai -> G3
|
|
||||||
Shinzan-Kinen -> G3
|
|
||||||
Fairy-Stakes -> G3
|
|
||||||
Aichi-Hai -> G3
|
|
||||||
Keisei-Hai -> G3
|
|
||||||
Silk-Road-Stakes -> G3
|
|
||||||
Negishi-Stakes -> G3
|
|
||||||
Kisaragi-Sho -> G3
|
|
||||||
Tokyo-Shimbun-Hai -> G3
|
|
||||||
Queen-Cup -> G3
|
|
||||||
Kyodo-News-Hai -> G3
|
|
||||||
Kyoto-Umamusume-Stakes -> G3
|
|
||||||
Diamond-Stakes -> G3
|
|
||||||
Kokura-Daishoten -> G3
|
|
||||||
Arlington-Cup -> G3
|
|
||||||
Hankyu-Hai -> G3
|
|
||||||
Ocean-Stakes -> G3
|
|
||||||
Nakayama-Umamusume-Stakes -> G3
|
|
||||||
Falcon-Stakes -> G3
|
|
||||||
Flower-Cup -> G3
|
|
||||||
Mainichi-Hai -> G3
|
|
||||||
March-Stakes -> G3
|
|
||||||
Lord-Derby-Challenge-Trophy -> G3
|
|
||||||
Antares-Stakes -> G3
|
|
||||||
Fukushima-Umamusume-Stakes -> G3
|
|
||||||
Niigata-Daishoten -> G3
|
|
||||||
Heian-Stakes -> G3
|
|
||||||
Aoi-Stakes -> G3
|
|
||||||
Naruo-Kinen -> G3
|
|
||||||
Mermaid-Stakes -> G3
|
|
||||||
Epsom-Cup -> G3
|
|
||||||
Unicorn-Stakes -> G3
|
|
||||||
Hakodate-Sprint-Stakes -> G3
|
|
||||||
CBC-Sho -> G3
|
|
||||||
Radio-Nikkei-Sho -> G3
|
|
||||||
Procyon-Stakes -> G3
|
|
||||||
Tanabata-Sho -> G3
|
|
||||||
Hakodate-Kinen -> G3
|
|
||||||
Chukyo-Kinen -> G3
|
|
||||||
Hakodate-Junior-Stakes -> G3
|
|
||||||
Ibis-Summer-Dash -> G3
|
|
||||||
Queen-Stakes -> G3
|
|
||||||
Kokura-Kinen -> G3
|
|
||||||
Leopard-Stakes -> G3
|
|
||||||
Sekiya-Kinen -> G3
|
|
||||||
Elm-Stakes -> G3
|
|
||||||
Kitakyushu-Kinen -> G3
|
|
||||||
Niigata-Junior-Stakes -> G3
|
|
||||||
Keeneland-Cup -> G3
|
|
||||||
Sapporo-Junior-Stakes -> G3
|
|
||||||
Kokura-Junior-Stakes -> G3
|
|
||||||
Niigata-Kinen -> G3
|
|
||||||
Shion-Stakes -> G3
|
|
||||||
Keisei-Hai-Autumn-Handicap -> G3
|
|
||||||
Sirius-Stakes -> G3
|
|
||||||
Saudi-Arabia-Royal-Cup -> G3
|
|
||||||
Artemis-Stakes -> G3
|
|
||||||
Fantasy-Stakes -> G3
|
|
||||||
Miyako-Stakes -> G3
|
|
||||||
Musashino-Stakes -> G3
|
|
||||||
Fukushima-Kinen -> G3
|
|
||||||
Tokyo-Sports-Hai-Junior-Stakes -> G3
|
|
||||||
Kyoto-Junior-Stakes -> G3
|
|
||||||
Keihan-Hai -> G3
|
|
||||||
Challenge-Cup -> G3
|
|
||||||
Chunichi-Shimbun-Hai -> G3
|
|
||||||
Capella-Stakes -> G3
|
|
||||||
Turquoise-Stakes -> G3
|
|
||||||
|
|
||||||
pub type title
|
|
||||||
Classic-Triple-Crown
|
|
||||||
Triple-Tiara
|
|
||||||
Senior-Spring-Triple-Crown
|
|
||||||
Senior-Autumn-Triple-Crown
|
|
||||||
Tenno-Sweep
|
|
||||||
Dual-Grand-Prix
|
|
||||||
Dual-Miles
|
|
||||||
Dual-Sprints
|
|
||||||
Dual-Dirts
|
|
||||||
|
|
||||||
// Get the titles that a race contributes to.
|
|
||||||
inline fun career-race/titles(r: career-race): list<title>
|
|
||||||
match r
|
|
||||||
Satsuki-Sho -> [Classic-Triple-Crown]
|
|
||||||
Japanese-Derby -> [Classic-Triple-Crown]
|
|
||||||
Kikuka-Sho -> [Classic-Triple-Crown]
|
|
||||||
Oka-Sho -> [Triple-Tiara]
|
|
||||||
Japanese-Oaks -> [Triple-Tiara]
|
|
||||||
Shuka-Sho -> [Triple-Tiara]
|
|
||||||
Osaka-Hai -> [Senior-Spring-Triple-Crown]
|
|
||||||
Tenno-Sho-Spring -> [Senior-Spring-Triple-Crown, Tenno-Sweep]
|
|
||||||
Takarazuka-Kinen -> [Senior-Spring-Triple-Crown, Dual-Grand-Prix]
|
|
||||||
Tenno-Sho-Autumn -> [Senior-Autumn-Triple-Crown, Tenno-Sweep]
|
|
||||||
Japan-Cup -> [Senior-Autumn-Triple-Crown]
|
|
||||||
Arima-Kinen -> [Senior-Autumn-Triple-Crown, Dual-Grand-Prix]
|
|
||||||
Yasuda-Kinen -> [Dual-Miles]
|
|
||||||
Mile-Championship -> [Dual-Miles]
|
|
||||||
Takamatsunomiya-Kinen -> [Dual-Sprints]
|
|
||||||
Sprinters-Stakes -> [Dual-Sprints]
|
|
||||||
February-Stakes -> [Dual-Dirts]
|
|
||||||
Champions-Cup -> [Dual-Dirts]
|
|
||||||
_ -> []
|
|
||||||
|
|
||||||
// Get the races that a title requires.
|
|
||||||
inline fun title/races(t: title): list<career-race>
|
|
||||||
match t
|
|
||||||
Classic-Triple-Crown -> [Satsuki-Sho, Japanese-Derby, Kikuka-Sho]
|
|
||||||
Triple-Tiara -> [Oka-Sho, Japanese-Oaks, Shuka-Sho]
|
|
||||||
Senior-Spring-Triple-Crown -> [Osaka-Hai, Tenno-Sho-Spring, Takarazuka-Kinen]
|
|
||||||
Senior-Autumn-Triple-Crown -> [Tenno-Sho-Autumn, Japan-Cup, Arima-Kinen]
|
|
||||||
Tenno-Sweep -> [Tenno-Sho-Spring, Tenno-Sho-Autumn]
|
|
||||||
Dual-Grand-Prix -> [Takarazuka-Kinen, Arima-Kinen]
|
|
||||||
Dual-Miles -> [Yasuda-Kinen, Mile-Championship]
|
|
||||||
Dual-Sprints -> [Takamatsunomiya-Kinen, Sprinters-Stakes]
|
|
||||||
Dual-Dirts -> [February-Stakes, Champions-Cup]
|
|
||||||
|
|
||||||
// Get all titles earned by an uma.
|
|
||||||
pub fun career/titles(results: list<race-result>): list<title>
|
|
||||||
val wins = results.flatmap-maybe() fn(r) (if r.place == 1 then Just(r.race) else Nothing)
|
|
||||||
val title-wins = wins.filter(_.titles.is-cons).linear-set
|
|
||||||
val titles = title-wins.list.flatmap(_.titles).linear-set.list
|
|
||||||
titles.filter(_.races.linear-set.is-subset-of(title-wins))
|
|
||||||
|
|
||||||
// Automatically generated.
|
// Automatically generated.
|
||||||
// Equality comparison of the `title` type.
|
// Shows a string representation of the `grade` type.
|
||||||
pub fun title/(==)(this : title, other : title) : e bool
|
pub fun grade/show(this : grade) : e string
|
||||||
|
match this
|
||||||
|
Pre-OP -> "Pre-OP"
|
||||||
|
OP -> "OP"
|
||||||
|
G3 -> "G3"
|
||||||
|
G2 -> "G2"
|
||||||
|
G1 -> "G1"
|
||||||
|
EX -> "EX"
|
||||||
|
|
||||||
|
pub struct saddle-detail
|
||||||
|
saddle-id: saddle-id
|
||||||
|
name: string
|
||||||
|
races: list<race-id>
|
||||||
|
saddle-type: saddle-type
|
||||||
|
// For careers with unusual races, granted saddles also differ.
|
||||||
|
// This field holds the normal saddle's ID for such cases.
|
||||||
|
primary: saddle-id
|
||||||
|
|
||||||
|
pub fun saddle/detail(
|
||||||
|
id: saddle-id,
|
||||||
|
?saddle/show: (saddle-id) -> string,
|
||||||
|
?saddle/races: (saddle-id) -> list<race-id>,
|
||||||
|
?saddle/saddle-type: (saddle-id) -> saddle-type,
|
||||||
|
?saddle/primary: (saddle-id) -> saddle-id
|
||||||
|
): saddle-detail
|
||||||
|
Saddle-detail(id, id.show, id.races, id.saddle-type, id.primary)
|
||||||
|
|
||||||
|
pub fun saddle-detail/show(s: saddle-detail): string
|
||||||
|
val Saddle-detail(Saddle-id(id), name, _, _, Saddle-id(primary)) = s
|
||||||
|
if id == primary then name else name ++ " (Alternate " ++ id.show ++ ")"
|
||||||
|
|
||||||
|
// Types of saddles.
|
||||||
|
pub type saddle-type
|
||||||
|
Honor // multiple race wins: classic triple crown, dual grand prix, &c.
|
||||||
|
G3-Win
|
||||||
|
G2-Win
|
||||||
|
G1-Win
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Shows a string representation of the `saddle-type` type.
|
||||||
|
pub fun saddle-type/show(this : saddle-type) : e string
|
||||||
|
match this
|
||||||
|
Honor -> "Honor"
|
||||||
|
G3-Win -> "G3"
|
||||||
|
G2-Win -> "G2"
|
||||||
|
G1-Win -> "G1"
|
||||||
|
|
||||||
|
// Automatically generated.
|
||||||
|
// Equality comparison of the `saddle-type` type.
|
||||||
|
pub fun saddle-type/(==)(this : saddle-type, other : saddle-type) : e bool
|
||||||
match (this, other)
|
match (this, other)
|
||||||
(Classic-Triple-Crown, Classic-Triple-Crown) -> True
|
(Honor, Honor) -> True
|
||||||
(Triple-Tiara, Triple-Tiara) -> True
|
(G3-Win, G3-Win) -> True
|
||||||
(Senior-Spring-Triple-Crown, Senior-Spring-Triple-Crown) -> True
|
(G2-Win, G2-Win) -> True
|
||||||
(Senior-Autumn-Triple-Crown, Senior-Autumn-Triple-Crown) -> True
|
(G1-Win, G1-Win) -> True
|
||||||
(Tenno-Sweep, Tenno-Sweep) -> True
|
|
||||||
(Dual-Grand-Prix, Dual-Grand-Prix) -> True
|
|
||||||
(Dual-Miles, Dual-Miles) -> True
|
|
||||||
(Dual-Sprints, Dual-Sprints) -> True
|
|
||||||
(Dual-Dirts, Dual-Dirts) -> True
|
|
||||||
(_, _) -> False
|
(_, _) -> False
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Shows a string representation of the `title` type.
|
|
||||||
pub fun title/show(this : title) : e string
|
|
||||||
match this
|
|
||||||
Classic-Triple-Crown -> "Classic Triple Crown"
|
|
||||||
Triple-Tiara -> "Triple Tiara"
|
|
||||||
Senior-Spring-Triple-Crown -> "Senior Spring Triple Crown"
|
|
||||||
Senior-Autumn-Triple-Crown -> "Senior Autumn Triple Crown"
|
|
||||||
Tenno-Sweep -> "Tenno Sweep"
|
|
||||||
Dual-Grand-Prix -> "Dual Grand Prix"
|
|
||||||
Dual-Miles -> "Dual Miles"
|
|
||||||
Dual-Sprints -> "Dual Sprints"
|
|
||||||
Dual-Dirts -> "Dual Dirts"
|
|
||||||
|
|
||||||
// Graded race that a veteran ran.
|
|
||||||
pub struct race-result
|
|
||||||
race: career-race
|
|
||||||
place: int
|
|
||||||
turn: turn
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Equality comparison of the `race-result` type.
|
|
||||||
pub fun race-result/(==)(this : race-result, other : race-result) : e bool
|
|
||||||
match (this, other)
|
|
||||||
(Race-result(race, place, turn), Race-result(race', place', turn')) -> race == race' && place == place' && turn == turn'
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Shows a string representation of the `race-result` type.
|
|
||||||
pub fun race-result/show(this : race-result) : e string
|
|
||||||
match this
|
|
||||||
Race-result(race, place, turn) -> turn.show ++ " " ++ race.show ++ ": " ++ place.show
|
|
||||||
|
|
||||||
// Determine whether two race results are for the same race.
|
|
||||||
// This differs from (==) which also requires the race to be on the same turn.
|
|
||||||
pub fun race-result/same(a: race-result, b: race-result): bool
|
|
||||||
a.race == b.race
|
|
||||||
|
|
||||||
// Turn that a race occurred.
|
// Turn that a race occurred.
|
||||||
pub struct turn
|
pub struct turn
|
||||||
year: turn-year
|
year: turn-year
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ type Skill struct {
|
|||||||
GradeValue int32
|
GradeValue int32
|
||||||
WitCheck bool
|
WitCheck bool
|
||||||
Activations []Activation
|
Activations []Activation
|
||||||
|
UniqueOwner string
|
||||||
SPCost int
|
SPCost int
|
||||||
IconID int
|
IconID int
|
||||||
}
|
}
|
||||||
@@ -72,7 +73,7 @@ func (a Ability) String() string {
|
|||||||
case AbilityVision:
|
case AbilityVision:
|
||||||
r = append(r, a.Value.String()...)
|
r = append(r, a.Value.String()...)
|
||||||
r = append(r, 'm')
|
r = append(r, 'm')
|
||||||
case AbilityHP, AbilityCurrentSpeed, AbilityTargetSpeed, AbilityLaneSpeed, AbilityAccel:
|
case AbilityHP:
|
||||||
r = append(r, (a.Value * 100).String()...)
|
r = append(r, (a.Value * 100).String()...)
|
||||||
r = append(r, '%')
|
r = append(r, '%')
|
||||||
case AbilityGateDelay:
|
case AbilityGateDelay:
|
||||||
@@ -81,12 +82,36 @@ func (a Ability) String() string {
|
|||||||
case AbilityFrenzy:
|
case AbilityFrenzy:
|
||||||
r = append(r, a.Value.String()...)
|
r = append(r, a.Value.String()...)
|
||||||
r = append(r, 's')
|
r = append(r, 's')
|
||||||
|
case AbilityCurrentSpeed, AbilityTargetSpeed, AbilityLaneSpeed:
|
||||||
|
r = append(r, a.Value.String()...)
|
||||||
|
r = append(r, " m/s"...)
|
||||||
|
case AbilityAccel:
|
||||||
|
r = append(r, a.Value.String()...)
|
||||||
|
r = append(r, " m/s²"...)
|
||||||
case AbilityLaneChange:
|
case AbilityLaneChange:
|
||||||
r = append(r, (a.Value * 100).String()...)
|
r = append(r, a.Value.String()...)
|
||||||
r = append(r, "% of track width"...)
|
r = append(r, " track widths"...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if a.Target != TargetSelf {
|
switch a.Target {
|
||||||
|
case TargetSelf:
|
||||||
|
// do nothing
|
||||||
|
case TargetStyle, TargetRushingStyle:
|
||||||
|
// TargetValue is the style to target, not the number of targets.
|
||||||
|
r = append(r, " to "...)
|
||||||
|
r = append(r, a.Target.String()...)
|
||||||
|
switch a.TargetValue {
|
||||||
|
case 1:
|
||||||
|
r = append(r, " Front Runner"...)
|
||||||
|
case 2:
|
||||||
|
r = append(r, " Pace Chaser"...)
|
||||||
|
case 3:
|
||||||
|
r = append(r, " Late Surger"...)
|
||||||
|
case 4:
|
||||||
|
r = append(r, " End Closer"...)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// For other targeting types, TargetValue is either irrelevant or limit.
|
||||||
r = append(r, " to "...)
|
r = append(r, " to "...)
|
||||||
if a.TargetValue > 1 && a.TargetValue < 18 {
|
if a.TargetValue > 1 && a.TargetValue < 18 {
|
||||||
r = strconv.AppendInt(r, int64(a.TargetValue), 10)
|
r = strconv.AppendInt(r, int64(a.TargetValue), 10)
|
||||||
@@ -126,12 +151,24 @@ type AbilityValueUsage int8
|
|||||||
|
|
||||||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityValueUsage -trimprefix ValueUsage -linecomment
|
//go:generate go run golang.org/x/tools/cmd/stringer@v0.41.0 -type AbilityValueUsage -trimprefix ValueUsage -linecomment
|
||||||
const (
|
const (
|
||||||
ValueUsageDirect AbilityValueUsage = 1 // directly
|
ValueUsageDirect AbilityValueUsage = 1 // directly
|
||||||
ValueUsageTeamSpeed AbilityValueUsage = 3 // scaling with team Speed
|
ValueUsageSkillCount AbilityValueUsage = 2 // scaling with the number of skills
|
||||||
ValueUsageTeamStamina AbilityValueUsage = 4 // scaling with team Stamina
|
ValueUsageTeamSpeed AbilityValueUsage = 3 // scaling with team Speed
|
||||||
ValueUsageTeamPower AbilityValueUsage = 5 // scaling with team Power
|
ValueUsageTeamStamina AbilityValueUsage = 4 // scaling with team Stamina
|
||||||
ValueUsageTeamGuts AbilityValueUsage = 6 // scaling with team Guts
|
ValueUsageTeamPower AbilityValueUsage = 5 // scaling with team Power
|
||||||
ValueUsageTeamWit AbilityValueUsage = 7 // scaling with team Wit
|
ValueUsageTeamGuts AbilityValueUsage = 6 // scaling with team Guts
|
||||||
|
ValueUsageTeamWit AbilityValueUsage = 7 // scaling with team Wit
|
||||||
|
ValueUsageRandom AbilityValueUsage = 8 // with a random 0× to 0.04× multiplier
|
||||||
|
ValueUsageRandom2 AbilityValueUsage = 9 // with a random 0× to 0.04× multiplier
|
||||||
|
ValueUsageClimax AbilityValueUsage = 10 // scaling with the number of races won in training
|
||||||
|
ValueUsageMaxStat AbilityValueUsage = 13 // scaling with the highest raw stat
|
||||||
|
ValueUsageGreenCount AbilityValueUsage = 14 // scaling with the number of Passive skills activated
|
||||||
|
ValueUsageDistAdd AbilityValueUsage = 19 // plus extra when far from the lead
|
||||||
|
ValueUsageMidSideBlock AbilityValueUsage = 20 // scaling with mid-race phase blocked side time
|
||||||
|
ValueUsageSpeed AbilityValueUsage = 22 // scaling with overall speed
|
||||||
|
ValueUsageSpeed2 AbilityValueUsage = 23 // scaling with overall speed
|
||||||
|
ValueUsageArcPotential AbilityValueUsage = 24 // scaling with L'Arc global potential
|
||||||
|
ValueUsageMaxLead AbilityValueUsage = 25 // scaling with the longest lead obtained in the first ⅔
|
||||||
)
|
)
|
||||||
|
|
||||||
type AbilityTarget int8
|
type AbilityTarget int8
|
||||||
|
|||||||
226
horse/skill.kk
Normal file
226
horse/skill.kk
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
module horse/skill
|
||||||
|
|
||||||
|
// This module contains skill-related definitions
|
||||||
|
// common to all versions of the game.
|
||||||
|
|
||||||
|
import std/num/decimal
|
||||||
|
import horse/game-id
|
||||||
|
import horse/movement
|
||||||
|
|
||||||
|
// Full details about a skill.
|
||||||
|
pub struct skill-detail
|
||||||
|
skill-id: skill-id
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
group-id: skill-group-id
|
||||||
|
rarity: rarity
|
||||||
|
group-rate: int
|
||||||
|
grade-value: int
|
||||||
|
wit-check: bool
|
||||||
|
activations: list<activation>
|
||||||
|
owner: maybe<trainee-id>
|
||||||
|
sp-cost: int
|
||||||
|
icon-id: skill-icon-id
|
||||||
|
|
||||||
|
pub fun detail(
|
||||||
|
s: skill-id,
|
||||||
|
?skill/show: (skill-id) -> string,
|
||||||
|
?skill/description: (skill-id) -> string,
|
||||||
|
?skill/group: (skill-id) -> skill-group-id,
|
||||||
|
?skill/rarity: (skill-id) -> rarity,
|
||||||
|
?skill/group-rate: (skill-id) -> int,
|
||||||
|
?skill/grade-value: (skill-id) -> int,
|
||||||
|
?skill/wit-check: (skill-id) -> bool,
|
||||||
|
?skill/activations: (skill-id) -> list<activation>,
|
||||||
|
?skill/unique-owner: (skill-id) -> maybe<trainee-id>,
|
||||||
|
?skill/sp-cost: (skill-id) -> int,
|
||||||
|
?skill/icon-id: (skill-id) -> skill-icon-id
|
||||||
|
): skill-detail
|
||||||
|
Skill-detail(
|
||||||
|
s,
|
||||||
|
s.show,
|
||||||
|
s.description,
|
||||||
|
s.group,
|
||||||
|
s.rarity,
|
||||||
|
s.group-rate,
|
||||||
|
s.grade-value,
|
||||||
|
s.wit-check,
|
||||||
|
s.activations,
|
||||||
|
s.unique-owner,
|
||||||
|
s.sp-cost,
|
||||||
|
s.icon-id
|
||||||
|
)
|
||||||
|
|
||||||
|
pub fun skill-detail/show(d: skill-detail, ?character/show: (character-id) -> string, ?trainee/show: (trainee-id) -> string): string
|
||||||
|
val Skill-detail(Skill-id(id), name, desc, _, rarity, _, grade-value, wit-check, activations, owner, sp-cost, _) = d
|
||||||
|
val r = name ++ " (ID " ++ id.show ++ "): " ++ desc ++ " " ++ activations.map(activation/show).join(". ") ++ (if wit-check then ". Wit check. " else ". No wit check. ") ++ rarity.show ++ " costing " ++ sp-cost.show ++ " SP, worth " ++ grade-value.show ++ " grade value."
|
||||||
|
match owner
|
||||||
|
Nothing -> r
|
||||||
|
Just(owner-id) -> match owner-id.show
|
||||||
|
"" -> r ++ " Unique skill of trainee with ID " ++ owner-id.show ++ "."
|
||||||
|
owner-name -> r ++ " Unique skill of " ++ owner-name ++ "."
|
||||||
|
|
||||||
|
// Skill rarity levels.
|
||||||
|
pub type rarity
|
||||||
|
Common // white
|
||||||
|
Rare // gold
|
||||||
|
Unique-Low // 1*/2* unique
|
||||||
|
Unique-Upgraded // 3*+ unique on a trainee upgraded from 1*/2*
|
||||||
|
Unique // base 3* unique
|
||||||
|
|
||||||
|
pub fun rarity/show(r: rarity): string
|
||||||
|
match r
|
||||||
|
Common -> "Common"
|
||||||
|
Rare -> "Rare"
|
||||||
|
Unique-Low -> "Unique (1\u2606/2\u2606)"
|
||||||
|
Unique-Upgraded -> "Unique (3\u2606+ from 1\u2606/2\u2606 upgraded)"
|
||||||
|
Unique -> "Unique (3\u2606+)"
|
||||||
|
|
||||||
|
// Condition and precondition logic.
|
||||||
|
pub alias condition = string
|
||||||
|
|
||||||
|
// Activation conditions and effects.
|
||||||
|
// A skill has one or two activations.
|
||||||
|
pub struct activation
|
||||||
|
precondition: condition
|
||||||
|
condition: condition
|
||||||
|
duration: decimal // seconds
|
||||||
|
cooldown: decimal // seconds
|
||||||
|
abilities: list<ability> // one to three elements
|
||||||
|
|
||||||
|
pub fun activation/show(a: activation, ?character/show: (character-id) -> string): string
|
||||||
|
match a
|
||||||
|
Activation("", condition, duration, _, abilities) | !duration.is-pos -> condition ++ " -> " ++ abilities.show
|
||||||
|
Activation("", condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> condition ++ " -> for " ++ duration.show ++ "s, " ++ abilities.show
|
||||||
|
Activation("", condition, duration, cooldown, abilities) -> condition ++ " -> for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
|
||||||
|
Activation(precondition, condition, duration, _, abilities) | !duration.is-pos -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show
|
||||||
|
Activation(precondition, condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s, " ++ abilities.show
|
||||||
|
Activation(precondition, condition, duration, cooldown, abilities) -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
|
||||||
|
|
||||||
|
// Effects of activating a skill.
|
||||||
|
pub struct ability
|
||||||
|
ability-type: ability-type
|
||||||
|
value-usage: value-usage
|
||||||
|
target: target
|
||||||
|
|
||||||
|
pub fun ability/show(a: ability, ?character/show: (character-id) -> string): string
|
||||||
|
match a
|
||||||
|
Ability(t, Direct, Self) -> t.show
|
||||||
|
Ability(t, Direct, target) -> t.show ++ " " ++ target.show
|
||||||
|
Ability(t, v, Self) -> t.show ++ " " ++ v.show
|
||||||
|
Ability(t, v, target) -> t.show ++ " " ++ target.show ++ " " ++ v.show
|
||||||
|
|
||||||
|
// Skill ability effects.
|
||||||
|
pub type ability-type
|
||||||
|
Passive-Speed(bonus: decimal)
|
||||||
|
Passive-Stamina(bonus: decimal)
|
||||||
|
Passive-Power(bonus: decimal)
|
||||||
|
Passive-Guts(bonus: decimal)
|
||||||
|
Passive-Wit(bonus: decimal)
|
||||||
|
Great-Escape
|
||||||
|
Vision(bonus: decimal)
|
||||||
|
HP(rate: decimal)
|
||||||
|
Gate-Delay(rate: decimal)
|
||||||
|
Frenzy(add: decimal)
|
||||||
|
Current-Speed(add: decimal)
|
||||||
|
Target-Speed(add: decimal)
|
||||||
|
Lane-Speed(add: decimal)
|
||||||
|
Accel(add: decimal)
|
||||||
|
Lane-Change(add: decimal)
|
||||||
|
|
||||||
|
pub fun ability-type/show(a: ability-type): string
|
||||||
|
match a
|
||||||
|
Passive-Speed(bonus) -> bonus.show ++ " Speed"
|
||||||
|
Passive-Stamina(bonus) -> bonus.show ++ " Stamina"
|
||||||
|
Passive-Power(bonus) -> bonus.show ++ " Power"
|
||||||
|
Passive-Guts(bonus) -> bonus.show ++ " Guts"
|
||||||
|
Passive-Wit(bonus) -> bonus.show ++ " Wit"
|
||||||
|
Great-Escape -> "enable Great Escape style"
|
||||||
|
Vision(bonus) -> bonus.show ++ " vision"
|
||||||
|
HP(rate) | rate.is-pos -> show(rate * 100.decimal) ++ "% HP recovery"
|
||||||
|
HP(rate) -> show(rate * 100.decimal) ++ "% HP loss"
|
||||||
|
Gate-Delay(rate) -> rate.show ++ "× gate delay"
|
||||||
|
Frenzy(add) -> add.show ++ "s longer Rushed"
|
||||||
|
Current-Speed(rate) -> rate.show ++ "m/s current speed"
|
||||||
|
Target-Speed(rate) -> rate.show ++ "m/s target speed"
|
||||||
|
Lane-Speed(rate) -> rate.show ++ "m/s lane change speed"
|
||||||
|
Accel(rate) -> rate.show ++ "m/s² acceleration"
|
||||||
|
Lane-Change(rate) -> rate.show ++ " course width movement"
|
||||||
|
|
||||||
|
// Special scaling types for skill abilities.
|
||||||
|
pub type value-usage
|
||||||
|
Direct
|
||||||
|
Team-Speed
|
||||||
|
Team-Stamina
|
||||||
|
Team-Power
|
||||||
|
Team-Guts
|
||||||
|
Team-Wit
|
||||||
|
Multiply-Random
|
||||||
|
Multiply-Random2
|
||||||
|
Climax
|
||||||
|
Max-Stat
|
||||||
|
Passive-Count
|
||||||
|
Front-Distance-Add
|
||||||
|
Midrace-Side-Block-Time
|
||||||
|
Speed-Scaling
|
||||||
|
Speed-Scaling2
|
||||||
|
Arc-Global-Potential
|
||||||
|
Max-Lead-Distance
|
||||||
|
|
||||||
|
pub fun value-usage/show(v: value-usage): string
|
||||||
|
match v
|
||||||
|
Direct -> "with no scaling"
|
||||||
|
Team-Speed -> "scaling with team Speed"
|
||||||
|
Team-Stamina -> "scaling with team Stamina"
|
||||||
|
Team-Power -> "scaling with team Power"
|
||||||
|
Team-Guts -> "scaling with team Guts"
|
||||||
|
Team-Wit -> "scaling with team Wit"
|
||||||
|
Multiply-Random -> "scaling with a random multiplier (0×, 0.02×, or 0.04×)"
|
||||||
|
Multiply-Random2 -> "scaling with a random multiplier (0×, 0.02×, or 0.04×)"
|
||||||
|
Climax -> "scaling with the number of races won during training"
|
||||||
|
Max-Stat -> "scaling with the value of the user's highest stat"
|
||||||
|
Passive-Count -> "scaling with the number of Passive skills activated"
|
||||||
|
Front-Distance-Add -> "scaling with distance from the leader"
|
||||||
|
Midrace-Side-Block-Time -> "scaling with mid-race phase blocked side time"
|
||||||
|
Speed-Scaling -> "scaling with overall speed"
|
||||||
|
Speed-Scaling2 -> "scaling with overall speed"
|
||||||
|
Arc-Global-Potential -> "scaling with L'Arc global potential"
|
||||||
|
Max-Lead-Distance -> "scaling with the distance of the longest lead obtained in the first two thirds of the race"
|
||||||
|
|
||||||
|
// Who a skill ability targets.
|
||||||
|
pub type target
|
||||||
|
Self
|
||||||
|
Sympathizers
|
||||||
|
In-View
|
||||||
|
Frontmost(limit: int)
|
||||||
|
Ahead(limit: int)
|
||||||
|
Behind(limit: int)
|
||||||
|
All-Teammates
|
||||||
|
Style(style: style)
|
||||||
|
Rushing-Ahead(limit: int)
|
||||||
|
Rushing-Behind(limit: int)
|
||||||
|
Rushing-Style(style: style)
|
||||||
|
Specific-Character(who: character-id)
|
||||||
|
Triggering
|
||||||
|
|
||||||
|
pub fun target/show(t: target, ?character/show: (character-id) -> string): string
|
||||||
|
match t
|
||||||
|
Self -> "self"
|
||||||
|
Sympathizers -> "others with Sympathy"
|
||||||
|
In-View -> "others in field of view"
|
||||||
|
Frontmost(limit) -> "frontmost " ++ limit.show
|
||||||
|
Ahead(limit) | limit >= 18 -> "others ahead"
|
||||||
|
Ahead(limit) -> "next " ++ limit.show ++ " others ahead"
|
||||||
|
Behind(limit) | limit >= 18 -> "others behind"
|
||||||
|
Behind(limit) -> "next " ++ limit.show ++ " others behind"
|
||||||
|
All-Teammates -> "all teammates"
|
||||||
|
Style(s) -> "other " ++ s.show ++ "s"
|
||||||
|
Rushing-Ahead(limit) | limit >= 18 -> "others rushing ahead"
|
||||||
|
Rushing-Ahead(limit) -> "next " ++ limit.show ++ " others rushing ahead"
|
||||||
|
Rushing-Behind(limit) | limit >= 18 -> "others rushing behind"
|
||||||
|
Rushing-Behind(limit) -> "next " ++ limit.show ++ " others rushing behind"
|
||||||
|
Rushing-Style(s) -> "rushing " ++ s.show ++ "s"
|
||||||
|
Specific-Character(who) -> match who.show
|
||||||
|
"" -> "character with ID " ++ who.show
|
||||||
|
name -> name
|
||||||
|
Triggering -> "whosoever triggered this skill"
|
||||||
@@ -1,70 +1,18 @@
|
|||||||
module horse/trainee
|
module horse/trainee
|
||||||
|
|
||||||
import std/data/rb-map
|
import horse/game-id
|
||||||
|
import horse/movement
|
||||||
|
import horse/race
|
||||||
|
|
||||||
// Aptitudes of an umamusume being trained.
|
// Details of a trainee.
|
||||||
pub struct uma
|
pub struct trainee-detail
|
||||||
turf: aptitudes
|
turf: level
|
||||||
dirt: aptitudes
|
dirt: level
|
||||||
sprint: aptitudes
|
sprint: level
|
||||||
mile: aptitudes
|
mile: level
|
||||||
medium: aptitudes
|
medium: level
|
||||||
long: aptitudes
|
long: level
|
||||||
front-runner: aptitudes
|
front-runner: level
|
||||||
pace-chaser: aptitudes
|
pace-chaser: level
|
||||||
late-surger: aptitudes
|
late-surger: level
|
||||||
end-closer: aptitudes
|
end-closer: level
|
||||||
|
|
||||||
// Aptitude level distribution.
|
|
||||||
pub alias aptitudes = rbmap<level, float64>
|
|
||||||
|
|
||||||
// Starting aptitude levels.
|
|
||||||
pub type level
|
|
||||||
G
|
|
||||||
F
|
|
||||||
E
|
|
||||||
D
|
|
||||||
C
|
|
||||||
B
|
|
||||||
A
|
|
||||||
S
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Fip comparison of the `level` type.
|
|
||||||
pub fun level/order2(this : level, other : level) : order2<level>
|
|
||||||
match (this, other)
|
|
||||||
(G, G) -> Eq2(G)
|
|
||||||
(G, other') -> Lt2(G, other')
|
|
||||||
(this', G) -> Gt2(G, this')
|
|
||||||
(F, F) -> Eq2(F)
|
|
||||||
(F, other') -> Lt2(F, other')
|
|
||||||
(this', F) -> Gt2(F, this')
|
|
||||||
(E, E) -> Eq2(E)
|
|
||||||
(E, other') -> Lt2(E, other')
|
|
||||||
(this', E) -> Gt2(E, this')
|
|
||||||
(D, D) -> Eq2(D)
|
|
||||||
(D, other') -> Lt2(D, other')
|
|
||||||
(this', D) -> Gt2(D, this')
|
|
||||||
(C, C) -> Eq2(C)
|
|
||||||
(C, other') -> Lt2(C, other')
|
|
||||||
(this', C) -> Gt2(C, this')
|
|
||||||
(B, B) -> Eq2(B)
|
|
||||||
(B, other') -> Lt2(B, other')
|
|
||||||
(this', B) -> Gt2(B, this')
|
|
||||||
(A, A) -> Eq2(A)
|
|
||||||
(A, other') -> Lt2(A, other')
|
|
||||||
(this', A) -> Gt2(A, this')
|
|
||||||
(S, S) -> Eq2(S)
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Shows a string representation of the `level` type.
|
|
||||||
pub fun level/show(this : level) : string
|
|
||||||
match this
|
|
||||||
G -> "G"
|
|
||||||
F -> "F"
|
|
||||||
E -> "E"
|
|
||||||
D -> "D"
|
|
||||||
C -> "C"
|
|
||||||
B -> "B"
|
|
||||||
A -> "A"
|
|
||||||
S -> "S"
|
|
||||||
|
|||||||
@@ -5,67 +5,55 @@ module horse/{{ $.Region }}/character
|
|||||||
|
|
||||||
import std/core/vector
|
import std/core/vector
|
||||||
import std/core-extras
|
import std/core-extras
|
||||||
|
import std/data/rb-map
|
||||||
|
import horse/game-id
|
||||||
|
pub import horse/character
|
||||||
|
|
||||||
// Character identity.
|
// Enumeration of all characters for type-safe programming.
|
||||||
pub type character
|
pub type character
|
||||||
{{- range $uma := $.Characters }}
|
{{- range $uma := $.Characters }}
|
||||||
{{ kkenum $uma.Name }}
|
{{ kkenum $uma.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
// The list of all characters in order by ID, for easy iterating.
|
// Get the character ID for a character.
|
||||||
pub val character/all = [
|
pub fun character-id(c: character): character-id
|
||||||
|
match c
|
||||||
|
{{- range $uma := $.Characters }}
|
||||||
|
{{ kkenum $uma.Name }} -> Character-id({{ $uma.ID }})
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// List of all characters in ID order for easy iterating.
|
||||||
|
pub val all = [
|
||||||
{{- range $uma := $.Characters }}
|
{{- range $uma := $.Characters }}
|
||||||
{{ kkenum $uma.Name }},
|
{{ kkenum $uma.Name }},
|
||||||
{{- end }}
|
{{- end }}
|
||||||
]
|
]
|
||||||
|
|
||||||
// Get the character for a character ID.
|
val name2id: rbmap<string, character-id> = rb-map/empty()
|
||||||
// Generally, these are four digit numbers in the range 1000-1999.
|
{{- range $uma := $.Characters }}
|
||||||
pub fun character/from-id(id: int): maybe<character>
|
.set({{ printf "%q" $uma.Name }}, Character-id({{ $uma.ID}}))
|
||||||
match id
|
{{- end }}
|
||||||
|
|
||||||
|
// Get the character ID that has the given exact name.
|
||||||
|
// If no character matches the name, the result is an invalid ID.
|
||||||
|
pub fun from-name(name: string): character-id
|
||||||
|
name2id.lookup(name).default(Character-id(0))
|
||||||
|
|
||||||
|
// Get the name for a character.
|
||||||
|
// If no character matches the ID, the result is the numeric ID.
|
||||||
|
pub fun show(c: character-id): string
|
||||||
|
match c.game-id
|
||||||
{{- range $uma := $.Characters }}
|
{{- range $uma := $.Characters }}
|
||||||
{{ $uma.ID }} -> Just( {{- kkenum $uma.Name -}} )
|
{{ $uma.ID }} -> {{ printf "%q" $uma.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
_ -> Nothing
|
x -> "character " ++ x.show
|
||||||
|
|
||||||
// Get the ID for a character.
|
fun character/index(c: character-id): int
|
||||||
pub fun character/character-id(c: character): int
|
match c.game-id
|
||||||
match c
|
|
||||||
{{- range $uma := $.Characters }}
|
{{- range $uma := $.Characters }}
|
||||||
{{ kkenum $uma.Name }} -> {{ $uma.ID }}
|
{{ $uma.ID }} -> {{ $uma.Index }}
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Get the name of a character.
|
|
||||||
pub fun character/show(c: character): string
|
|
||||||
match c
|
|
||||||
{{- range $uma := $.Characters }}
|
|
||||||
{{ kkenum $uma.Name }} -> {{ printf "%q" $uma.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Compare two characters.
|
|
||||||
pub fip fun character/order2(a: character, b: character): order2<character>
|
|
||||||
match (a, b)
|
|
||||||
{{- range $uma := $.Characters }}{{ $e := kkenum $uma.Name }}
|
|
||||||
( {{- $e }}, {{ $e -}} ) -> Eq2( {{- $e -}} )
|
|
||||||
{{- if ne $uma.ID $.MaxID }}
|
|
||||||
( {{- $e }}, b') -> Lt2( {{- $e }}, b')
|
|
||||||
(a', {{ $e -}} ) -> Gt2( {{- $e }}, a')
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Character equality.
|
|
||||||
pub fun character/(==)(a: character, b: character): bool
|
|
||||||
match (a, b)
|
|
||||||
{{- range $uma := $.Characters }}{{ $e := kkenum $uma.Name }}
|
|
||||||
( {{- $e }}, {{ $e -}} ) -> True
|
|
||||||
{{- end }}
|
|
||||||
_ -> False
|
|
||||||
|
|
||||||
fip fun character/index(^c: character): int
|
|
||||||
match c
|
|
||||||
{{- range $uma := $.Characters }}
|
|
||||||
{{ kkenum $uma.Name }} -> {{ $uma.Index }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
_ -> -99999999
|
||||||
|
|
||||||
// Create the table of all pair affinities.
|
// Create the table of all pair affinities.
|
||||||
// The affinity is the value at a.index*count + b.index.
|
// The affinity is the value at a.index*count + b.index.
|
||||||
@@ -87,7 +75,7 @@ extern global/create-pair-table(): vector<int>
|
|||||||
val global/pair-table = global/create-pair-table()
|
val global/pair-table = global/create-pair-table()
|
||||||
|
|
||||||
// Base affinity between a pair using the global ruleset.
|
// Base affinity between a pair using the global ruleset.
|
||||||
pub fun global/pair-affinity(a: character, b: character): int
|
pub fun global/pair-affinity(a: character-id, b: character-id): int
|
||||||
global/pair-table.at(a.index * {{ $.Count }} + b.index).default(0)
|
global/pair-table.at(a.index * {{ $.Count }} + b.index).default(0)
|
||||||
|
|
||||||
// Create the table of all trio affinities.
|
// Create the table of all trio affinities.
|
||||||
@@ -114,7 +102,7 @@ extern global/create-trio-table(): vector<int>
|
|||||||
val global/trio-table = global/create-trio-table()
|
val global/trio-table = global/create-trio-table()
|
||||||
|
|
||||||
// Base affinity for a trio using the global ruleset.
|
// Base affinity for a trio using the global ruleset.
|
||||||
pub fun global/trio-affinity(a: character, b: character, c: character): int
|
pub fun global/trio-affinity(a: character-id, b: character-id, c: character-id): int
|
||||||
global/trio-table.at(a.index * {{ $.Count }} * {{ $.Count }} + b.index * {{ $.Count }} + c.index).default(0)
|
global/trio-table.at(a.index * {{ $.Count }} * {{ $.Count }} + b.index * {{ $.Count }} + c.index).default(0)
|
||||||
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed character.kk.template skill.kk.template character.go.template skill.go.template
|
//go:embed *.template
|
||||||
var templates embed.FS
|
var templates embed.FS
|
||||||
|
|
||||||
// LoadTemplates sets up templates to render game data to source code.
|
// LoadTemplates sets up templates to render game data to source code.
|
||||||
@@ -64,10 +64,10 @@ func ExecCharacter(t *template.Template, region string, kk, g io.Writer, c []Nam
|
|||||||
}{region, c, pairs, trios, pm, tm, len(c), maxid}
|
}{region, c, pairs, trios, pm, tm, len(c), maxid}
|
||||||
var err error
|
var err error
|
||||||
if kk != nil {
|
if kk != nil {
|
||||||
err = errors.Join(t.ExecuteTemplate(kk, "koka-character", &data))
|
err = errors.Join(err, t.ExecuteTemplate(kk, "koka-character", &data))
|
||||||
}
|
}
|
||||||
if g != nil {
|
if g != nil {
|
||||||
err = errors.Join(t.ExecuteTemplate(g, "go-character", &data))
|
err = errors.Join(err, t.ExecuteTemplate(g, "go-character", &data))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -85,21 +85,42 @@ func ExecSkill(t *template.Template, region string, kk, g io.Writer, groups []Na
|
|||||||
}{region, groups, skills, m}
|
}{region, groups, skills, m}
|
||||||
var err error
|
var err error
|
||||||
if kk != nil {
|
if kk != nil {
|
||||||
err = errors.Join(t.ExecuteTemplate(kk, "koka-skill", &data))
|
err = errors.Join(err, t.ExecuteTemplate(kk, "koka-skill", &data))
|
||||||
}
|
}
|
||||||
if g != nil {
|
if g != nil {
|
||||||
err = errors.Join(t.ExecuteTemplate(g, "go-skill-data", &data))
|
err = errors.Join(err, t.ExecuteTemplate(g, "go-skill-data", &data))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecSkillGroupKK(t *template.Template, region string, w io.Writer, g []NamedID[SkillGroup], s []Skill) error {
|
func ExecRace(t *template.Template, region string, kk, g io.Writer, races []Race) error {
|
||||||
data := struct {
|
data := struct {
|
||||||
Region string
|
Region string
|
||||||
Groups []NamedID[SkillGroup]
|
Races []Race
|
||||||
Skills []Skill
|
}{region, races}
|
||||||
}{region, g, s}
|
var err error
|
||||||
return t.ExecuteTemplate(w, "koka-skill-group", &data)
|
if kk != nil {
|
||||||
|
err = errors.Join(err, t.ExecuteTemplate(kk, "koka-race", &data))
|
||||||
|
}
|
||||||
|
if g != nil {
|
||||||
|
err = errors.Join(err, t.ExecuteTemplate(g, "go-race", &data))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecSaddle(t *template.Template, region string, kk, g io.Writer, saddles []Saddle) error {
|
||||||
|
data := struct {
|
||||||
|
Region string
|
||||||
|
Saddles []Saddle
|
||||||
|
}{region, saddles}
|
||||||
|
var err error
|
||||||
|
if kk != nil {
|
||||||
|
err = errors.Join(err, t.ExecuteTemplate(kk, "koka-saddle", &data))
|
||||||
|
}
|
||||||
|
if g != nil {
|
||||||
|
err = errors.Join(err, t.ExecuteTemplate(g, "go-saddle", &data))
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
const wordSeps = " ,!?/-+();#○☆♡'=♪∀゚∴"
|
const wordSeps = " ,!?/-+();#○☆♡'=♪∀゚∴"
|
||||||
@@ -111,13 +132,15 @@ var (
|
|||||||
"1,500,000 CC", "One-Million-CC",
|
"1,500,000 CC", "One-Million-CC",
|
||||||
"15,000,000 CC", "Fifteen-Million-CC",
|
"15,000,000 CC", "Fifteen-Million-CC",
|
||||||
"1st", "First",
|
"1st", "First",
|
||||||
|
"114th", "Hundred-Fourteenth",
|
||||||
"♡ 3D Nail Art", "Nail-Art",
|
"♡ 3D Nail Art", "Nail-Art",
|
||||||
".", "",
|
".", "",
|
||||||
|
"\u2019", "",
|
||||||
"&", "-and-",
|
"&", "-and-",
|
||||||
"'s", "s",
|
"'s", "s",
|
||||||
"ó", "o",
|
"ó", "o",
|
||||||
"∞", "Infinity",
|
"∞", "Infinity",
|
||||||
"×", "x",
|
"\u00d7", "x",
|
||||||
"◎", "Lv2",
|
"◎", "Lv2",
|
||||||
}
|
}
|
||||||
for _, c := range wordSeps {
|
for _, c := range wordSeps {
|
||||||
@@ -136,10 +159,11 @@ var (
|
|||||||
"1st", "First",
|
"1st", "First",
|
||||||
"♡ 3D Nail Art", "NailArt",
|
"♡ 3D Nail Art", "NailArt",
|
||||||
".", "",
|
".", "",
|
||||||
|
"\u2019", "",
|
||||||
"&", "And",
|
"&", "And",
|
||||||
"'s", "s",
|
"'s", "s",
|
||||||
"∞", "Infinity",
|
"∞", "Infinity",
|
||||||
"×", "X",
|
"\u00d7", "X",
|
||||||
"◎", "Lv2",
|
"◎", "Lv2",
|
||||||
}
|
}
|
||||||
for _, c := range wordSeps {
|
for _, c := range wordSeps {
|
||||||
@@ -159,6 +183,7 @@ func kkenum(name string) string {
|
|||||||
}
|
}
|
||||||
name = strings.ToUpper(name[:1]) + name[1:]
|
name = strings.ToUpper(name[:1]) + name[1:]
|
||||||
if !unicode.IsLetter(rune(name[0])) {
|
if !unicode.IsLetter(rune(name[0])) {
|
||||||
|
//lint:ignore ST1005 proper name
|
||||||
panic(fmt.Errorf("Koka enum variant %q (from %q) starts with a non-letter", name, orig))
|
panic(fmt.Errorf("Koka enum variant %q (from %q) starts with a non-letter", name, orig))
|
||||||
}
|
}
|
||||||
for _, c := range name {
|
for _, c := range name {
|
||||||
|
|||||||
132
horsegen/load.go
132
horsegen/load.go
@@ -23,6 +23,12 @@ var skillGroupSQL string
|
|||||||
//go:embed skill.sql
|
//go:embed skill.sql
|
||||||
var skillSQL string
|
var skillSQL string
|
||||||
|
|
||||||
|
//go:embed race.sql
|
||||||
|
var raceSQL string
|
||||||
|
|
||||||
|
//go:embed saddle.sql
|
||||||
|
var saddleSQL string
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Character struct{}
|
Character struct{}
|
||||||
SkillGroup struct{}
|
SkillGroup struct{}
|
||||||
@@ -179,20 +185,22 @@ func SkillGroups(ctx context.Context, db *sqlitex.Pool) ([]NamedID[SkillGroup],
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Skill struct {
|
type Skill struct {
|
||||||
ID int
|
ID int
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
GroupID int
|
GroupID int
|
||||||
GroupName string
|
GroupName string
|
||||||
Rarity int
|
Rarity int
|
||||||
GroupRate int
|
GroupRate int
|
||||||
GradeValue int
|
GradeValue int
|
||||||
WitCheck bool
|
WitCheck bool
|
||||||
Activations [2]SkillActivation
|
Activations [2]SkillActivation
|
||||||
SPCost int
|
SPCost int
|
||||||
InheritID int
|
InheritID int
|
||||||
IconID int
|
UniqueOwnerID int
|
||||||
Index int
|
UniqueOwner string
|
||||||
|
IconID int
|
||||||
|
Index int
|
||||||
}
|
}
|
||||||
|
|
||||||
type SkillActivation struct {
|
type SkillActivation struct {
|
||||||
@@ -302,10 +310,98 @@ func Skills(ctx context.Context, db *sqlitex.Pool) ([]Skill, error) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SPCost: stmt.ColumnInt(47),
|
SPCost: stmt.ColumnInt(47),
|
||||||
InheritID: stmt.ColumnInt(48),
|
InheritID: stmt.ColumnInt(48),
|
||||||
IconID: stmt.ColumnInt(49),
|
UniqueOwnerID: stmt.ColumnInt(49),
|
||||||
Index: stmt.ColumnInt(50),
|
UniqueOwner: stmt.ColumnText(50),
|
||||||
|
IconID: stmt.ColumnInt(51),
|
||||||
|
Index: stmt.ColumnInt(52),
|
||||||
|
}
|
||||||
|
r = append(r, s)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Race struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Grade int
|
||||||
|
ThumbnailID int
|
||||||
|
Primary int
|
||||||
|
Alternate int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Races(ctx context.Context, db *sqlitex.Pool) ([]Race, error) {
|
||||||
|
conn, err := db.Take(ctx)
|
||||||
|
defer db.Put(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't get connection for races: %w", err)
|
||||||
|
}
|
||||||
|
stmt, _, err := conn.PrepareTransient(raceSQL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't prepare statement for races: %w", err)
|
||||||
|
}
|
||||||
|
defer stmt.Finalize()
|
||||||
|
|
||||||
|
var r []Race
|
||||||
|
for {
|
||||||
|
ok, err := stmt.Step()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error stepping races: %w", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
race := Race{
|
||||||
|
ID: stmt.ColumnInt(0),
|
||||||
|
Name: stmt.ColumnText(1),
|
||||||
|
Grade: stmt.ColumnInt(2),
|
||||||
|
ThumbnailID: stmt.ColumnInt(3),
|
||||||
|
Primary: stmt.ColumnInt(4),
|
||||||
|
Alternate: stmt.ColumnInt(5),
|
||||||
|
}
|
||||||
|
r = append(r, race)
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Saddle struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Races [3]int
|
||||||
|
Type int
|
||||||
|
Primary int
|
||||||
|
Alternate int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Saddles(ctx context.Context, db *sqlitex.Pool) ([]Saddle, error) {
|
||||||
|
conn, err := db.Take(ctx)
|
||||||
|
defer db.Put(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't get connection for saddles: %w", err)
|
||||||
|
}
|
||||||
|
stmt, _, err := conn.PrepareTransient(saddleSQL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't prepare statement for saddles: %w", err)
|
||||||
|
}
|
||||||
|
defer stmt.Finalize()
|
||||||
|
|
||||||
|
var r []Saddle
|
||||||
|
for {
|
||||||
|
ok, err := stmt.Step()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error stepping saddles: %w", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s := Saddle{
|
||||||
|
ID: stmt.ColumnInt(0),
|
||||||
|
Name: stmt.ColumnText(1),
|
||||||
|
Races: [3]int{stmt.ColumnInt(2), stmt.ColumnInt(3), stmt.ColumnInt(4)},
|
||||||
|
Type: stmt.ColumnInt(5),
|
||||||
|
Primary: stmt.ColumnInt(6),
|
||||||
|
Alternate: stmt.ColumnInt(7),
|
||||||
}
|
}
|
||||||
r = append(r, s)
|
r = append(r, s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func main() {
|
|||||||
region string
|
region string
|
||||||
)
|
)
|
||||||
flag.StringVar(&mdb, "mdb", os.ExpandEnv(`$USERPROFILE\AppData\LocalLow\Cygames\Umamusume\master\master.mdb`), "`path` to Umamusume master.mdb")
|
flag.StringVar(&mdb, "mdb", os.ExpandEnv(`$USERPROFILE\AppData\LocalLow\Cygames\Umamusume\master\master.mdb`), "`path` to Umamusume master.mdb")
|
||||||
flag.StringVar(&out, "o", `.\horse`, "`dir`ectory for output files")
|
flag.StringVar(&out, "o", `horse`, "`dir`ectory for output files")
|
||||||
flag.StringVar(®ion, "region", "global", "region the database is for (global, jp)")
|
flag.StringVar(®ion, "region", "global", "region the database is for (global, jp)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -45,11 +45,13 @@ func main() {
|
|||||||
|
|
||||||
eg, ctx := errgroup.WithContext(pctx)
|
eg, ctx := errgroup.WithContext(pctx)
|
||||||
var (
|
var (
|
||||||
charas []NamedID[Character]
|
charas []NamedID[Character]
|
||||||
pairs []AffinityRelation
|
pairs []AffinityRelation
|
||||||
trios []AffinityRelation
|
trios []AffinityRelation
|
||||||
sg []NamedID[SkillGroup]
|
sg []NamedID[SkillGroup]
|
||||||
skills []Skill
|
skills []Skill
|
||||||
|
races []Race
|
||||||
|
saddles []Saddle
|
||||||
)
|
)
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
slog.Info("get characters")
|
slog.Info("get characters")
|
||||||
@@ -81,6 +83,18 @@ func main() {
|
|||||||
skills = r
|
skills = r
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
eg.Go(func() error {
|
||||||
|
slog.Info("get races")
|
||||||
|
r, err := Races(ctx, db)
|
||||||
|
races = r
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
eg.Go(func() error {
|
||||||
|
slog.Info("get saddles")
|
||||||
|
s, err := Saddles(ctx, db)
|
||||||
|
saddles = s
|
||||||
|
return err
|
||||||
|
})
|
||||||
if err := eg.Wait(); err != nil {
|
if err := eg.Wait(); err != nil {
|
||||||
slog.Error("load", slog.Any("err", err))
|
slog.Error("load", slog.Any("err", err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -110,19 +124,39 @@ func main() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gf, err := os.Create(filepath.Join(out, region, "skill.go"))
|
gf, err := os.Create(filepath.Join(out, region, "skill.go"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
slog.Info("write skills")
|
slog.Info("write skills")
|
||||||
return ExecSkill(t, region, sf, gf, sg, skills)
|
return ExecSkill(t, region, sf, gf, sg, skills)
|
||||||
})
|
})
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
sf, err := os.Create(filepath.Join(out, region, "skill-group.kk"))
|
kf, err := os.Create(filepath.Join(out, region, "race.kk"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slog.Info("write skill groups")
|
gf, err := os.Create(filepath.Join(out, region, "race.go"))
|
||||||
return ExecSkillGroupKK(t, region, sf, sg, skills)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
slog.Info("write races")
|
||||||
|
return ExecRace(t, region, kf, gf, races)
|
||||||
|
})
|
||||||
|
eg.Go(func() error {
|
||||||
|
kf, err := os.Create(filepath.Join(out, region, "saddle.kk"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gf, err := os.Create(filepath.Join(out, region, "saddle.go"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
slog.Info("write saddles")
|
||||||
|
return ExecSaddle(t, region, kf, gf, saddles)
|
||||||
})
|
})
|
||||||
if err := eg.Wait(); err != nil {
|
if err := eg.Wait(); err != nil {
|
||||||
slog.Error("generate", slog.Any("err", err))
|
slog.Error("generate", slog.Any("err", err))
|
||||||
|
os.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
slog.Info("done")
|
slog.Info("done")
|
||||||
}
|
}
|
||||||
|
|||||||
32
horsegen/race.go.template
Normal file
32
horsegen/race.go.template
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{{- define "go-race" -}}
|
||||||
|
package {{ $.Region }}
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import . "git.sunturtle.xyz/zephyr/horse/horse"
|
||||||
|
|
||||||
|
const (
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
Race{{ goenum $r.Name }}{{ if $r.Alternate }}Alt{{ $r.ID }}{{ end }} RaceID = {{ $r.ID }} // {{ $r.Name }}
|
||||||
|
{{- end }}
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllRaces = map[RaceID]Race{
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
Race{{ goenum $r.Name }}{{ if $r.Alternate }}Alt{{ $r.ID }}{{ end }}: {
|
||||||
|
ID: {{ $r.ID }},
|
||||||
|
Name: {{ printf "%q" $r.Name }}{{ if $r.Alternate }} + " (Alternate {{ $r.ID }})"{{ end }},
|
||||||
|
Thumbnail: {{ $r.ThumbnailID }},
|
||||||
|
{{- if ne $r.Primary $r.ID }}
|
||||||
|
Primary: {{ $r.Primary }},
|
||||||
|
{{- end }}
|
||||||
|
},
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
var RaceNameToID = map[string]RaceID{
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ printf "%q" $r.Name }}{{ if $r.Alternate }} + " (Alternate {{ $r.ID }})"{{ end }}: {{ $r.ID }},
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
80
horsegen/race.kk.template
Normal file
80
horsegen/race.kk.template
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
{{- define "koka-race" -}}
|
||||||
|
module horse/{{ $.Region }}/race
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import std/data/rb-map
|
||||||
|
import horse/game-id
|
||||||
|
pub import horse/race
|
||||||
|
|
||||||
|
// Enumeration of all races for type-safe programming.
|
||||||
|
pub type race
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ kkenum $r.Name }}{{ if $r.Alternate }}-Alt{{ $r.ID }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Get the race ID for a race.
|
||||||
|
pub fun race-id(r: race): race-id
|
||||||
|
match r
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ kkenum $r.Name }}{{ if $r.Alternate }}-Alt{{ $r.ID }}{{ end }} -> Race-id({{ $r.ID }})
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// List of all races in ID order for easy iterating.
|
||||||
|
pub val all = [
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ kkenum $r.Name }}{{ if $r.Alternate }}-Alt{{ $r.ID }}{{ end }},
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
|
||||||
|
val name2id: rbmap<string, race-id> = rb-map/empty()
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
.set({{ printf "%q" $r.Name }}{{ if $r.Alternate }} ++ " (Alternate {{ $r.ID }})"{{ end }}, Race-id({{ $r.ID }}))
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Get the race ID that has the given exact name.
|
||||||
|
// Alternate versions of races have an indication of their ID in their names.
|
||||||
|
// If no race matches the name, the result is an invalid ID.
|
||||||
|
pub fun from-name(name: string): race-id
|
||||||
|
name2id.lookup(name).default(Race-id(0))
|
||||||
|
|
||||||
|
// Get the name for a race.
|
||||||
|
// Alternate versions of races have an indication of their ID in their names.
|
||||||
|
// If no race matches the ID, the result is the numeric ID.
|
||||||
|
pub fun show(r: race-id): string
|
||||||
|
match r.game-id
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ $r.ID }} -> {{ printf "%q" $r.Name }}{{ if $r.Alternate }} ++ " (Alternate {{ $r.ID }})"{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
x -> "race " ++ x.show
|
||||||
|
|
||||||
|
// Get the grade for a race.
|
||||||
|
// If no race matches the ID, the result is Pre-OP.
|
||||||
|
pub fun grade(r: race-id): grade
|
||||||
|
match r.game-id
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ $r.ID }} -> {{ if eq $r.Grade 100 }}G1{{ else if eq $r.Grade 200 }}G2{{ else if eq $r.Grade 300 }}G3{{ else if eq $r.Grade 400 }}OP{{ else if eq $r.Grade 700 }}Pre-OP{{ else }}??? $r.Grade={{ $r.Grade }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> Pre-OP
|
||||||
|
|
||||||
|
// Get the thumbnail ID for a race.
|
||||||
|
// If no race matches the ID, the result is an invalid ID.
|
||||||
|
pub fun thumbnail(r: race-id): race-thumbnail-id
|
||||||
|
match r.game-id
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{ $r.ID }} -> Race-thumbnail-id({{ $r.ThumbnailID }})
|
||||||
|
{{- end }}
|
||||||
|
_ -> Race-thumbnail-id(0)
|
||||||
|
|
||||||
|
// Get the primary ID for a race.
|
||||||
|
// For races which are the primary version, or if no race matches the given ID,
|
||||||
|
// the result is the input.
|
||||||
|
pub fun primary(r: race-id): race-id
|
||||||
|
match r.game-id
|
||||||
|
{{- range $r := $.Races }}
|
||||||
|
{{- if $r.Alternate }}
|
||||||
|
{{ $r.ID }} -> Race-id({{ $r.Primary }})
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> r
|
||||||
|
{{ end }}
|
||||||
14
horsegen/race.sql
Normal file
14
horsegen/race.sql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
WITH race_names AS (
|
||||||
|
SELECT "index" AS id, "text" AS name FROM text_data WHERE category = 33
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
race.id,
|
||||||
|
race_names.name,
|
||||||
|
race.grade,
|
||||||
|
race.thumbnail_id,
|
||||||
|
MIN(race.id) OVER (PARTITION BY race_names.name) AS "primary",
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY race_names.name ORDER BY race.id) - 1 AS "alternate"
|
||||||
|
FROM race
|
||||||
|
JOIN race_names ON race.id = race_names.id
|
||||||
|
WHERE race."group" = 1
|
||||||
|
ORDER BY race.id
|
||||||
27
horsegen/saddle.go.template
Normal file
27
horsegen/saddle.go.template
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{{- define "go-saddle" -}}
|
||||||
|
package {{ $.Region }}
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import . "git.sunturtle.xyz/zephyr/horse/horse"
|
||||||
|
|
||||||
|
const (
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
Saddle{{ goenum $s.Name }}{{ if $s.Alternate }}Alt{{ $s.Alternate }}{{ end }} SaddleID = {{ $s.ID }} // {{ $s.Name }}
|
||||||
|
{{- end }}
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllSaddles = map[SaddleID]Saddle{
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
Saddle{{ goenum $s.Name }}{{ if $s.Alternate }}Alt{{ $s.Alternate }}{{ end }}: {
|
||||||
|
ID: {{ $s.ID }},
|
||||||
|
Name: {{ printf "%q" $s.Name }}{{ if $s.Alternate }} + " (Alternate {{ $s.Alternate }})"{{ end }},
|
||||||
|
Races: []RaceID{ {{- range $id := $s.Races }}{{ if $id }}{{ $id }}, {{ end }}{{ end -}} },
|
||||||
|
Type: SaddleType{{ if eq $s.Type 0 }}Honor{{ else if eq $s.Type 1 }}G3{{ else if eq $s.Type 2 }}G2{{ else if eq $s.Type 3 }}G1{{ else }}??? $s.Type={{ $s.Type }}{{ end }},
|
||||||
|
{{- if $s.Alternate }}
|
||||||
|
Primary: {{ $s.Primary }},
|
||||||
|
{{- end }}
|
||||||
|
},
|
||||||
|
{{- end }}
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
69
horsegen/saddle.kk.template
Normal file
69
horsegen/saddle.kk.template
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
{{- define "koka-saddle" -}}
|
||||||
|
module horse/{{ $.Region }}/saddle
|
||||||
|
|
||||||
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import horse/game-id
|
||||||
|
pub import horse/race
|
||||||
|
pub import horse/{{ $.Region }}/race
|
||||||
|
|
||||||
|
// Enumeration of all saddles for type-safe programming.
|
||||||
|
pub type saddle
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{ kkenum $s.Name }}{{ if $s.Alternate }}-Alt{{ $s.ID }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Get the saddle ID for a saddle.
|
||||||
|
pub fun saddle-id(s: saddle): saddle-id
|
||||||
|
match s
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{ kkenum $s.Name }}{{ if $s.Alternate }}-Alt{{ $s.ID }}{{ end }} -> Saddle-id({{ $s.ID }})
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// List of all saddles in ID order for easy iterating.
|
||||||
|
pub val all = [
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{ kkenum $s.Name }}{{ if $s.Alternate }}-Alt{{ $s.ID }}{{ end }},
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
|
||||||
|
// Get the name for a saddle.
|
||||||
|
// Alternate versions of saddles have an indication of their ID in their names.
|
||||||
|
// If no saddle matches the ID, the result contains the numeric ID.
|
||||||
|
pub fun show(s: saddle-id): string
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{ $s.ID }} -> {{ printf "%q" $s.Name }}{{ if $s.Alternate }} ++ " (Alternate {{ $s.ID }})"{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
x -> "saddle " ++ x.show
|
||||||
|
|
||||||
|
// Get the list of races that entitle a horse to a saddle.
|
||||||
|
// If no saddle matches the ID, the result is the empty list.
|
||||||
|
pub fun races(s: saddle-id): list<race-id>
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{ $s.ID }} -> [{{ range $id := $s.Races }}{{ if $id }}Race-id({{ $id }}), {{ end }}{{ end }}]
|
||||||
|
{{- end }}
|
||||||
|
_ -> []
|
||||||
|
|
||||||
|
// Get a saddle's type.
|
||||||
|
// If no saddle matches the ID, the result is Honor.
|
||||||
|
pub fun saddle-type(s: saddle-id): saddle-type
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{ $s.ID }} -> {{ if eq $s.Type 0 }}Honor{{ else if eq $s.Type 1 }}G3-Win{{ else if eq $s.Type 2 }}G2-Win{{ else if eq $s.Type 3 }}G1-Win{{ else }}??? $s.Type={{ $s.Type }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> Honor
|
||||||
|
|
||||||
|
// Get the primary ID for a saddle.
|
||||||
|
// For saddles which are the primary version, or if no saddle matches the given ID,
|
||||||
|
// the result is the input.
|
||||||
|
pub fun primary(s: saddle-id): saddle-id
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Saddles }}
|
||||||
|
{{- if $s.Alternate }}
|
||||||
|
{{ $s.ID }} -> Saddle-id({{ $s.Primary }})
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> s
|
||||||
|
{{ end }}
|
||||||
20
horsegen/saddle.sql
Normal file
20
horsegen/saddle.sql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
WITH saddle_names AS (
|
||||||
|
SELECT "index" AS id, "text" AS name
|
||||||
|
FROM text_data
|
||||||
|
WHERE category = 111
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
s.id,
|
||||||
|
n.name,
|
||||||
|
ri1.id AS race1,
|
||||||
|
IFNULL(ri2.id, 0) AS race2,
|
||||||
|
IFNULL(ri3.id, 0) AS race3,
|
||||||
|
s.win_saddle_type,
|
||||||
|
MIN(s.id) OVER (PARTITION BY n.name) AS "primary",
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY n.name ORDER BY s.id) - 1 AS "alternate"
|
||||||
|
FROM single_mode_wins_saddle s
|
||||||
|
JOIN race_instance ri1 ON s.race_instance_id_1 = ri1.id
|
||||||
|
LEFT JOIN race_instance ri2 ON s.race_instance_id_2 = ri2.id
|
||||||
|
LEFT JOIN race_instance ri3 ON s.race_instance_id_3 = ri3.id
|
||||||
|
LEFT JOIN saddle_names n ON s.id = n.id
|
||||||
|
ORDER BY s.id
|
||||||
@@ -53,6 +53,9 @@ var AllSkills = map[SkillID]Skill{
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
},
|
},
|
||||||
|
{{- if $s.UniqueOwner }}
|
||||||
|
UniqueOwner: {{ printf "%q" $s.UniqueOwner }},
|
||||||
|
{{- end }}
|
||||||
{{- if $s.SPCost }}
|
{{- if $s.SPCost }}
|
||||||
SPCost: {{ $s.SPCost }},
|
SPCost: {{ $s.SPCost }},
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -1,347 +1,233 @@
|
|||||||
{{- define "koka-skill-group" -}}
|
|
||||||
module horse/{{ $.Region }}/skill-group
|
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
|
||||||
|
|
||||||
// Skill groups.
|
|
||||||
// A skill group may contain white, circle, double-circle, gold, and purple skills
|
|
||||||
// for the same effect.
|
|
||||||
// Sparks that grant skills refer to a skill group.
|
|
||||||
pub type skill-group
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ kkenum $g.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Map a skill group to its ID.
|
|
||||||
pub fip fun skill-group/group-id(^sg: skill-group): int
|
|
||||||
match sg
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ kkenum $g.Name }} -> {{ $g.ID }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Get the skill group for an ID.
|
|
||||||
pub fip(1) fun skill-group/from-id(^id: int): maybe<skill-group>
|
|
||||||
match id
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ $g.ID }} -> Just( {{- kkenum $g.Name -}} )
|
|
||||||
{{- end }}
|
|
||||||
_ -> Nothing
|
|
||||||
|
|
||||||
// Get the name for a skill group.
|
|
||||||
// Skill group names are the name of the base skill in the group.
|
|
||||||
pub fun skill-group/show(sg: skill-group): string
|
|
||||||
match sg
|
|
||||||
{{- range $g := $.Groups }}
|
|
||||||
{{ kkenum $g.Name }} -> {{ printf "%q" $g.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
// Compare two skill groups by ID order.
|
|
||||||
pub fip fun skill-group/order2(a: skill-group, b: skill-group): order2<skill-group>
|
|
||||||
match cmp(a.group-id, b.group-id)
|
|
||||||
Lt -> Lt2(a, b)
|
|
||||||
Eq -> Eq2(a)
|
|
||||||
Gt -> Gt2(a, b)
|
|
||||||
|
|
||||||
pub fun skill-group/(==)(a: skill-group, b: skill-group): bool
|
|
||||||
a.group-id == b.group-id
|
|
||||||
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{- define "koka-skill" -}}
|
{{- define "koka-skill" -}}
|
||||||
module horse/{{ $.Region }}/skill
|
module horse/{{ $.Region }}/skill
|
||||||
|
|
||||||
// Automatically generated with horsegen; DO NOT EDIT
|
// Automatically generated with horsegen; DO NOT EDIT
|
||||||
|
|
||||||
|
import std/data/rb-map
|
||||||
import std/num/decimal
|
import std/num/decimal
|
||||||
pub import horse/{{ $.Region }}/skill-group
|
import horse/game-id
|
||||||
|
import horse/movement
|
||||||
|
pub import horse/skill
|
||||||
|
|
||||||
// Skill instances.
|
// Enumeration of all skills for type-safe programming.
|
||||||
pub type skill
|
pub type skill
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end -}}
|
{{ kkenum $s.Name }}{{ if $s.InheritID }}-Inherit{{ end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
// Map a skill to its ID.
|
// Get the skill ID for a skill.
|
||||||
pub fip fun skill/skill-id(^s: skill): int
|
pub fun skill-id(s: skill): skill-id
|
||||||
match s
|
match s
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }} -> {{ $s.ID }}
|
{{ kkenum $s.Name }}{{ if $s.InheritID }}-Inherit{{ end }} -> Skill-id({{ $s.ID }})
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
// Get the skill for an ID.
|
// List of all skills in ID order for easy iterating.
|
||||||
pub fip(1) fun skill/from-id(^id: int): maybe<skill>
|
pub val all = [
|
||||||
match id
|
{{- range $s := $.Skills }}
|
||||||
|
{{ kkenum $s.Name }}{{ if $s.InheritID }}-Inherit{{ end }},
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
|
||||||
|
val name2id: rbmap<string, skill-id> = rb-map/empty()
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
.set({{ printf "%q" $s.Name }}{{ if $s.InheritID }} ++ " (Inherited)"{{ end }}, Skill-id({{ $s.ID }}))
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
// Get the skill ID that has the given exact name.
|
||||||
|
// Inherited skills have `" (Inherited)"` appended to their names.
|
||||||
|
// If no skill matches the name, the result is an invalid ID.
|
||||||
|
pub fun from-name(name: string): skill-id
|
||||||
|
name2id.lookup(name).default(Skill-id(0))
|
||||||
|
|
||||||
|
// Get the name for a skill.
|
||||||
|
// Inherited skills have `" (Inherited)"` appended to their names.
|
||||||
|
// If no skill matches the ID, the result is the numeric ID.
|
||||||
|
pub fun show(s: skill-id): string
|
||||||
|
match s.game-id
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ $s.ID }} -> Just( {{- kkenum $s.Name -}}{{ if ne $s.InheritID 0 }}-Inherit{{ end -}} )
|
{{ $s.ID }} -> {{ printf "%q" $s.Name }}{{ if $s.InheritID }} ++ " (Inherited)"{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
x -> "skill " ++ x.show
|
||||||
|
|
||||||
|
// Get the description for a skill.
|
||||||
|
// If no skill matches the ID, the result is the empty string.
|
||||||
|
pub fun description(s: skill-id): string
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ printf "%q" $s.Description }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> ""
|
||||||
|
|
||||||
|
// Get the skill group ID for a skill.
|
||||||
|
// If no skill matches the ID, the result is an invalid ID.
|
||||||
|
pub fun group(s: skill-id): skill-group-id
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> Skill-group-id( {{- $s.GroupID -}} )
|
||||||
|
{{- end }}
|
||||||
|
_ -> Skill-group-id(0)
|
||||||
|
|
||||||
|
// Get the rarity of a skill.
|
||||||
|
// If no skill matches the ID, the result is Common.
|
||||||
|
pub fun rarity(s: skill-id): rarity
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ if eq $s.Rarity 1 }}Common{{ else if eq $s.Rarity 2 }}Rare{{ else if eq $s.Rarity 3 }}Unique-Low{{ else if eq $s.Rarity 4 }}Unique-Upgraded{{ else if eq $s.Rarity 5 }}Unique{{ else }}??? $s.Rarity={{ $s.Rarity }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> Common
|
||||||
|
|
||||||
|
// Get the group rate of a skill.
|
||||||
|
// If no skill matches the ID, the result is 0.
|
||||||
|
pub fun group-rate(s: skill-id): int
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ $s.GroupRate }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
|
// Get the grade value of a skill.
|
||||||
|
// If no skill matches the ID, the result is 0.
|
||||||
|
pub fun grade-value(s: skill-id): int
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ $s.GradeValue }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
|
// Get whether a skill is a wit check.
|
||||||
|
// If no skill matches the ID, the result is False.
|
||||||
|
pub fun wit-check(s: skill-id): bool
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> {{ if $s.WitCheck }}True{{ else }}False{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
// Get the activations of a skill.
|
||||||
|
// If no skill matches the ID, the result is an empty list.
|
||||||
|
pub fun activations(s: skill-id): list<activation>
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{ $s.ID }} -> [
|
||||||
|
{{- range $a := $s.Activations }}
|
||||||
|
{{- if $a.Condition }}
|
||||||
|
Activation(
|
||||||
|
precondition = {{ printf "%q" $a.Precondition }},
|
||||||
|
condition = {{ printf "%q" $a.Condition }},
|
||||||
|
duration = {{ $a.Duration }}.decimal{{ if gt $a.Duration 0 }}(-4){{ end }},
|
||||||
|
cooldown = {{ $a.Cooldown }}.decimal{{ if gt $a.Cooldown 0 }}(-4){{ end }},
|
||||||
|
abilities = [
|
||||||
|
{{- range $abil := $a.Abilities }}
|
||||||
|
{{- if $abil.Type }}
|
||||||
|
Ability(
|
||||||
|
ability-type = {{ if eq $abil.Type 1 }}Passive-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 2 }}Passive-Stamina({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 3 }}Passive-Power({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 4 }}Passive-Guts({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 5 }}Passive-Wit({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 6 }}Great-Escape
|
||||||
|
{{- else if eq $abil.Type 8 }}Vision({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 9 }}HP({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 10 }}Gate-Delay({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 13 }}Frenzy({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 21 }}Current-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 27 }}Target-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 28 }}Lane-Speed({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 31 }}Accel({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else if eq $abil.Type 35 }}Lane-Change({{ $abil.Value }}.decimal(-4))
|
||||||
|
{{- else }}??? $abil.Type={{$abil.Type}}
|
||||||
|
{{- end }},
|
||||||
|
value-usage = {{ if eq $abil.ValueUsage 1 }}Direct
|
||||||
|
{{- else if eq $abil.ValueUsage 3 }}Team-Speed
|
||||||
|
{{- else if eq $abil.ValueUsage 4 }}Team-Stamina
|
||||||
|
{{- else if eq $abil.ValueUsage 5 }}Team-Power
|
||||||
|
{{- else if eq $abil.ValueUsage 6 }}Team-Guts
|
||||||
|
{{- else if eq $abil.ValueUsage 7 }}Team-Wit
|
||||||
|
{{- else if eq $abil.ValueUsage 8 }}Multiply-Random
|
||||||
|
{{- else if eq $abil.ValueUsage 9 }}Multiply-Random2
|
||||||
|
{{- else if eq $abil.ValueUsage 10 }}Climax
|
||||||
|
{{- else if eq $abil.ValueUsage 13 }}Max-Stat
|
||||||
|
{{- else if eq $abil.ValueUsage 14 }}Passive-Count
|
||||||
|
{{- else if eq $abil.ValueUsage 19 }}Front-Distance-Add
|
||||||
|
{{- else if eq $abil.ValueUsage 20 }}Midrace-Side-Block-Time
|
||||||
|
{{- else if eq $abil.ValueUsage 22 }}Speed-Scaling
|
||||||
|
{{- else if eq $abil.ValueUsage 23 }}Speed-Scaling2
|
||||||
|
{{- else if eq $abil.ValueUsage 24 }}Arc-Global-Potential
|
||||||
|
{{- else if eq $abil.ValueUsage 25 }}Max-Lead-Distance
|
||||||
|
{{- else }}??? $abil.ValueUsage={{ $abil.ValueUsage }}
|
||||||
|
{{- end }},
|
||||||
|
target = {{ if eq $abil.Target 1}}Self
|
||||||
|
{{- else if eq $abil.Target 4 }}Sympathizers
|
||||||
|
{{- else if eq $abil.Target 4 }}In-View
|
||||||
|
{{- else if eq $abil.Target 4 }}Frontmost
|
||||||
|
{{- else if eq $abil.Target 9 }}Ahead({{ $abil.TargetValue }})
|
||||||
|
{{- else if eq $abil.Target 10 }}Behind({{ $abil.TargetValue }})
|
||||||
|
{{- else if eq $abil.Target 4 }}All-Teammates
|
||||||
|
{{- else if eq $abil.Target 18 }}Style({{ if eq $abil.TargetValue 1 }}Front-Runner{{ else if eq $abil.TargetValue 2 }}Pace-Chaser{{ else if eq $abil.TargetValue 3 }}Late-Surger{{ else if eq $abil.TargetValue 4 }}End-Closer{{ else }}??? $abil.TargetValue={{ $abil.TargetValue }}{{ end }})
|
||||||
|
{{- else if eq $abil.Target 19 }}Rushing-Ahead({{ $abil.TargetValue }})
|
||||||
|
{{- else if eq $abil.Target 20 }}Rushing-Behind({{ $abil.TargetValue }})
|
||||||
|
{{- else if eq $abil.Target 21 }}Rushing-Style({{ if eq $abil.TargetValue 1 }}Front-Runner{{ else if eq $abil.TargetValue 2 }}Pace-Chaser{{ else if eq $abil.TargetValue 3 }}Late-Surger{{ else if eq $abil.TargetValue 4 }}End-Closer{{ else }}??? $abil.TargetValue={{ $abil.TargetValue }}{{ end }})
|
||||||
|
{{- else if eq $abil.Target 22 }}Specific-Character(Character-id({{ $abil.TargetValue }}))
|
||||||
|
{{- else if eq $abil.Target 23 }}Triggering
|
||||||
|
{{- end }}
|
||||||
|
),
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
),
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
]
|
||||||
|
{{- end }}
|
||||||
|
_ -> Nil
|
||||||
|
|
||||||
|
// Get the owner of a unique skill.
|
||||||
|
// If the skill is not unique, or if there is no skill with the given ID,
|
||||||
|
// the result is Nothing.
|
||||||
|
pub fun unique-owner(s: skill-id): maybe<trainee-id>
|
||||||
|
match s.game-id
|
||||||
|
{{- range $s := $.Skills }}
|
||||||
|
{{- if $s.UniqueOwnerID }}
|
||||||
|
{{ $s.ID }} -> Just(Trainee-id({{ $s.UniqueOwnerID }}))
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
// Get the name of a skill.
|
// Get the SP cost of a skill.
|
||||||
// Inherited skills have the same names as their original counterparts.
|
// If there is no skill with the given ID, the result is 0.
|
||||||
pub fun skill/show(s: skill): string
|
pub fun sp-cost(s: skill-id): int
|
||||||
match s
|
match s.game-id
|
||||||
{{- range $s := $.Skills }}
|
{{- range $s := $.Skills }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }} -> {{ printf "%q" $s.Name }}
|
{{ $s.ID }} -> {{ $s.SPCost }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
// Compare two skills by ID order.
|
// Get the icon ID of a skill.
|
||||||
pub fip fun skill/order2(a: skill, b: skill): order2<skill>
|
// If there is no skill with the given ID, the result is an invalid ID.
|
||||||
match cmp(a.skill-id, b.skill-id)
|
pub fun icon-id(s: skill-id): skill-icon-id
|
||||||
Lt -> Lt2(a, b)
|
match s.game-id
|
||||||
Eq -> Eq2(a)
|
{{- range $s := $.Skills }}
|
||||||
Gt -> Gt2(a, b)
|
{{ $s.ID }} -> Skill-icon-id({{ $s.IconID }})
|
||||||
|
{{- end }}
|
||||||
|
_ -> Skill-icon-id(0)
|
||||||
|
|
||||||
pub fun skill/(==)(a: skill, b: skill): bool
|
// Get the name for a skill group.
|
||||||
a.skill-id == b.skill-id
|
// Skill group names are the name of the base skill in the group.
|
||||||
|
// If there is no skill group with the given ID, the result is the numeric ID.
|
||||||
// Get the skills in a skill group.
|
pub fun skill-group/show(sg: skill-group-id): string
|
||||||
pub fun skill-group/skills(g: skill-group): list<skill>
|
match sg.game-id
|
||||||
match g
|
|
||||||
{{- range $g := $.Groups }}
|
{{- range $g := $.Groups }}
|
||||||
{{ kkenum $g.Name }} -> [ {{- range $s := index $.Related $g.ID }}{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }}, {{ end }}]
|
{{ $g.ID }} -> {{- printf "%q" $g.Name -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
x -> "skill group " ++ x.show
|
||||||
|
|
||||||
// Get complete skill info.
|
// Get the list of skills in a skill group.
|
||||||
pub fun skill/detail(^s: skill): skill-detail
|
pub fun skill-group/skills(sg: skill-group-id): list<skill-id>
|
||||||
match s
|
match sg.game-id
|
||||||
{{- range $s := $.Skills }}
|
{{- range $g := $.Groups }}
|
||||||
{{ kkenum $s.Name }}{{ if ne $s.InheritID 0 }}-Inherit{{ end }} -> {{ template "kk-render-skill-detail" $s }}
|
{{ $g.ID }} -> [ {{- range $s := index $.Related $g.ID }}Skill-id({{ $s.ID }}), {{ end -}} ]
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
_ -> Nil
|
||||||
|
|
||||||
// Details about a skill.
|
{{- end }}
|
||||||
pub struct skill-detail
|
|
||||||
skill-id: int
|
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
group: maybe<skill-group>
|
|
||||||
rarity: rarity
|
|
||||||
group-rate: int
|
|
||||||
grade-value: int
|
|
||||||
wit-check: bool
|
|
||||||
activations: list<activation>
|
|
||||||
sp-cost: int
|
|
||||||
icon-id: int
|
|
||||||
|
|
||||||
// Automatically generated.
|
|
||||||
// Shows a string representation of the `skill-detail` type.
|
|
||||||
pub fun skill-detail/show(this : skill-detail) : e string
|
|
||||||
match this
|
|
||||||
Skill-detail(skill-id, name, description, group, rarity, group-rate, grade-value, wit-check, activations, sp-cost, icon-id) -> "Skill-detail(skill-id: " ++ skill-id.show ++ ", name: " ++ name.show ++ ", description: " ++ description.show ++ ", group: " ++ group.show ++ ", rarity: " ++ rarity.show ++ ", group-rate: " ++ group-rate.show ++ ", grade-value: " ++ grade-value.show ++ ", wit-check: " ++ wit-check.show ++ ", activations: " ++ activations.show ++ ", sp-cost: " ++ sp-cost.show ++ ", icon-id: " ++ icon-id.show ++ ")"
|
|
||||||
|
|
||||||
// Skill rarity.
|
|
||||||
pub type rarity
|
|
||||||
Common // white
|
|
||||||
Rare // gold
|
|
||||||
Unique-Low // 1*/2* unique
|
|
||||||
Unique-Upgraded // 3*+ unique on a trainee upgraded from 1*/2*
|
|
||||||
Unique // base 3* unique
|
|
||||||
|
|
||||||
pub fun rarity/show(r: rarity): string
|
|
||||||
match r
|
|
||||||
Common -> "Common"
|
|
||||||
Rare -> "Rare"
|
|
||||||
Unique-Low -> "Unique (1\u2606/2\u2606)"
|
|
||||||
Unique-Upgraded -> "Unique (3\u2606+ from 1\u2606/2\u2606 upgraded)"
|
|
||||||
Unique -> "Unique (3\u2606+)"
|
|
||||||
|
|
||||||
// Condition and precondition logic.
|
|
||||||
pub alias condition = string
|
|
||||||
|
|
||||||
// Activation conditions and effects.
|
|
||||||
// A skill has one or two activations.
|
|
||||||
pub struct activation
|
|
||||||
precondition: condition
|
|
||||||
condition: condition
|
|
||||||
duration: decimal // seconds
|
|
||||||
cooldown: decimal // seconds
|
|
||||||
abilities: list<ability> // one to three elements
|
|
||||||
|
|
||||||
pub fun activation/show(a: activation): string
|
|
||||||
match a
|
|
||||||
Activation("", condition, duration, _, abilities) | duration <= 0.decimal -> condition ++ " -> " ++ abilities.show
|
|
||||||
Activation("", condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s"
|
|
||||||
Activation("", condition, duration, cooldown, abilities) -> condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown"
|
|
||||||
Activation(precondition, condition, duration, _, abilities) | duration <= 0.decimal -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show
|
|
||||||
Activation(precondition, condition, duration, cooldown, abilities) | cooldown >= 500.decimal -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s"
|
|
||||||
Activation(precondition, condition, duration, cooldown, abilities) -> precondition ++ "-> " ++ condition ++ " -> " ++ abilities.show ++ " for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown"
|
|
||||||
|
|
||||||
// Effects of activating a skill.
|
|
||||||
pub struct ability
|
|
||||||
ability-type: ability-type
|
|
||||||
value-usage: value-usage
|
|
||||||
target: target
|
|
||||||
|
|
||||||
pub fun ability/show(a: ability): string
|
|
||||||
match a
|
|
||||||
Ability(t, Direct, Self) -> t.show
|
|
||||||
Ability(t, Direct, target) -> t.show ++ " " ++ target.show
|
|
||||||
Ability(t, v, Self) -> t.show ++ " scaling by " ++ v.show
|
|
||||||
Ability(t, v, target) -> t.show ++ " " ++ target.show ++ " scaling by " ++ v.show
|
|
||||||
|
|
||||||
// Target of a skill activation effect.
|
|
||||||
pub type ability-type
|
|
||||||
Passive-Speed(bonus: decimal)
|
|
||||||
Passive-Stamina(bonus: decimal)
|
|
||||||
Passive-Power(bonus: decimal)
|
|
||||||
Passive-Guts(bonus: decimal)
|
|
||||||
Passive-Wit(bonus: decimal)
|
|
||||||
Great-Escape
|
|
||||||
Vision(bonus: decimal)
|
|
||||||
HP(rate: decimal)
|
|
||||||
Gate-Delay(rate: decimal)
|
|
||||||
Frenzy(add: decimal)
|
|
||||||
Current-Speed(rate: decimal)
|
|
||||||
Target-Speed(rate: decimal)
|
|
||||||
Lane-Speed(rate: decimal)
|
|
||||||
Accel(rate: decimal)
|
|
||||||
Lane-Change(rate: decimal)
|
|
||||||
|
|
||||||
pub fun ability-type/show(a: ability-type): string
|
|
||||||
match a
|
|
||||||
Passive-Speed(bonus) -> "passive " ++ bonus.show ++ " Speed"
|
|
||||||
Passive-Stamina(bonus) -> "passive " ++ bonus.show ++ " Stamina"
|
|
||||||
Passive-Power(bonus) -> "passive " ++ bonus.show ++ " Power"
|
|
||||||
Passive-Guts(bonus) -> "passive " ++ bonus.show ++ " Guts"
|
|
||||||
Passive-Wit(bonus) -> "passive " ++ bonus.show ++ " Wit"
|
|
||||||
Great-Escape -> "enable Great Escape style"
|
|
||||||
Vision(bonus) -> bonus.show ++ " vision"
|
|
||||||
HP(rate) | rate >= 0.decimal -> show(rate * 100.decimal) ++ "% HP recovery"
|
|
||||||
HP(rate) -> show(rate * 100.decimal) ++ "% HP loss"
|
|
||||||
Gate-Delay(rate) -> rate.show ++ "× gate delay"
|
|
||||||
Frenzy(add) -> add.show ++ "s longer Rushed"
|
|
||||||
Current-Speed(rate) -> show(rate * 100.decimal) ++ "% current speed"
|
|
||||||
Target-Speed(rate) -> show(rate * 100.decimal) ++ "% target speed"
|
|
||||||
Lane-Speed(rate) -> show(rate * 100.decimal) ++ "% lane speed"
|
|
||||||
Accel(rate) -> show(rate * 100.decimal) ++ "% acceleration"
|
|
||||||
Lane-Change(rate) -> rate.show ++ " course width movement"
|
|
||||||
|
|
||||||
// Special scaling for skill activation effects.
|
|
||||||
pub type value-usage
|
|
||||||
Direct
|
|
||||||
Team-Speed
|
|
||||||
Team-Stamina
|
|
||||||
Team-Power
|
|
||||||
Team-Guts
|
|
||||||
Team-Wit
|
|
||||||
Multiply-Random
|
|
||||||
|
|
||||||
pub fun value-usage/show(v: value-usage): string
|
|
||||||
match v
|
|
||||||
Direct -> "no scaling"
|
|
||||||
Team-Speed -> "team's Speed"
|
|
||||||
Team-Stamina -> "team's Stamina"
|
|
||||||
Team-Power -> "team's Power"
|
|
||||||
Team-Guts -> "team's Guts"
|
|
||||||
Team-Wit -> "team's Wit"
|
|
||||||
Multiply-Random -> "random multiplier (0×, 0.02×, or 0.04×)"
|
|
||||||
|
|
||||||
// Who a skill activation targets.
|
|
||||||
pub type target
|
|
||||||
Self
|
|
||||||
In-View
|
|
||||||
Ahead(limit: int)
|
|
||||||
Behind(limit: int)
|
|
||||||
Style(style: style)
|
|
||||||
Rushing-Ahead(limit: int)
|
|
||||||
Rushing-Behind(limit: int)
|
|
||||||
Rushing-Style(style: style)
|
|
||||||
|
|
||||||
pub fun target/show(t: target): string
|
|
||||||
match t
|
|
||||||
Self -> "self"
|
|
||||||
In-View -> "others in field of view"
|
|
||||||
Ahead(limit) | limit >= 18 -> "others ahead"
|
|
||||||
Ahead(limit) -> "next " ++ limit.show ++ " others ahead"
|
|
||||||
Behind(limit) | limit >= 18 -> "others behind"
|
|
||||||
Behind(limit) -> "next " ++ limit.show ++ " others behind"
|
|
||||||
Style(Front-Runner) -> "other Front Runners"
|
|
||||||
Style(Pace-Chaser) -> "other Pace Chasers"
|
|
||||||
Style(Late-Surger) -> "other Late Surgers"
|
|
||||||
Style(End-Closer) -> "other End Closers"
|
|
||||||
Rushing-Ahead(limit) | limit >= 18 -> "others rushing ahead"
|
|
||||||
Rushing-Ahead(limit) -> "next " ++ limit.show ++ " others rushing ahead"
|
|
||||||
Rushing-Behind(limit) | limit >= 18 -> "others rushing behind"
|
|
||||||
Rushing-Behind(limit) -> "next " ++ limit.show ++ " others rushing behind"
|
|
||||||
Rushing-Style(Front-Runner) -> "rushing Front Runners"
|
|
||||||
Rushing-Style(Pace-Chaser) -> "rushing Pace Chasers"
|
|
||||||
Rushing-Style(Late-Surger) -> "rushing Late Surgers"
|
|
||||||
Rushing-Style(End-Closer) -> "rushing End Closers"
|
|
||||||
|
|
||||||
// Running style for skill targets.
|
|
||||||
{{- /* TODO(zeph): there is definitely a better place for this to live */}}
|
|
||||||
pub type style
|
|
||||||
Front-Runner
|
|
||||||
Pace-Chaser
|
|
||||||
Late-Surger
|
|
||||||
End-Closer
|
|
||||||
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{ define "kk-render-skill-detail" }}
|
|
||||||
{{- /* Call with Skill structure as argument. */ -}}
|
|
||||||
Skill-detail(skill-id = {{ $.ID -}}
|
|
||||||
, name = {{ printf "%q" $.Name -}}
|
|
||||||
, description = {{ printf "%q" $.Description -}}
|
|
||||||
, group = {{ if ne $.GroupName "" }}Just({{ kkenum $.GroupName }}){{ else }}Nothing{{ end -}}
|
|
||||||
, rarity = {{ if eq $.Rarity 1 }}Common{{ else if eq $.Rarity 2 }}Rare{{ else if eq $.Rarity 3 }}Unique-Low{{ else if eq $.Rarity 4 }}Unique-Upgraded{{ else if eq $.Rarity 5 }}Unique{{ else }}??? $.Rarity={{ $.Rarity }}{{ end -}}
|
|
||||||
, group-rate = {{ $.GroupRate -}}
|
|
||||||
, grade-value = {{ $.GradeValue -}}
|
|
||||||
, wit-check = {{ if $.WitCheck }}True{{ else }}False{{ end -}}
|
|
||||||
, activations = [
|
|
||||||
{{- range $a := $.Activations -}}
|
|
||||||
{{- if ne $a.Condition "" -}}
|
|
||||||
Activation(precondition = {{ printf "%q" $a.Precondition -}}
|
|
||||||
, condition = {{ printf "%q" $a.Condition -}}
|
|
||||||
, duration = {{ $a.Duration -}}{{ if gt $a.Duration 0 }}.decimal(-4){{ else }}.decimal{{ end -}}
|
|
||||||
, cooldown = {{ $a.Cooldown -}}{{ if gt $a.Cooldown 0 }}.decimal(-4){{ else }}.decimal{{ end -}}
|
|
||||||
, abilities = [
|
|
||||||
{{- range $abil := $a.Abilities -}}
|
|
||||||
{{- if ne $abil.Type 0 -}}
|
|
||||||
Ability(ability-type =
|
|
||||||
{{- if eq $abil.Type 1 -}}Passive-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 2 -}}Passive-Stamina({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 3 -}}Passive-Power({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 4 -}}Passive-Guts({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 5 -}}Passive-Wit({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 6 -}}Great-Escape
|
|
||||||
{{- else if eq $abil.Type 8 -}}Vision({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 9 -}}HP({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 10 -}}Gate-Delay({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 13 -}}Frenzy({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 21 -}}Current-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 27 -}}Target-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 28 -}}Lane-Speed({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 31 -}}Accel({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else if eq $abil.Type 35 -}}Lane-Change({{ $abil.Value }}.decimal(-4))
|
|
||||||
{{- else -}}??? $abil.Type={{$abil.Type}}
|
|
||||||
{{- end -}}
|
|
||||||
, value-usage =
|
|
||||||
{{- if eq $abil.ValueUsage 1 -}}Direct
|
|
||||||
{{- else if eq $abil.ValueUsage 3 -}}Team-Speed
|
|
||||||
{{- else if eq $abil.ValueUsage 4 -}}Team-Stamina
|
|
||||||
{{- else if eq $abil.ValueUsage 5 -}}Team-Power
|
|
||||||
{{- else if eq $abil.ValueUsage 6 -}}Team-Guts
|
|
||||||
{{- else if eq $abil.ValueUsage 7 -}}Team-Wit
|
|
||||||
{{- else if eq $abil.ValueUsage 8 -}}Multiply-Random
|
|
||||||
{{- else -}}??? $abil.ValueUsage={{ $abil.ValueUsage }}
|
|
||||||
{{- end -}}
|
|
||||||
, target =
|
|
||||||
{{- if eq $abil.Target 1 -}}Self
|
|
||||||
{{- else if eq $abil.Target 4 -}}In-View
|
|
||||||
{{- else if eq $abil.Target 9 -}}Ahead({{ $abil.TargetValue }})
|
|
||||||
{{- else if eq $abil.Target 10 -}}Behind({{ $abil.TargetValue }})
|
|
||||||
{{- else if eq $abil.Target 18 -}}Style({{ if eq $abil.TargetValue 1 }}Front-Runner{{ else if eq $abil.TargetValue 2 }}Pace-Chaser{{ else if eq $abil.TargetValue 3 }}Late-Surger{{ else if eq $abil.TargetValue 4 }}End-Closer{{ else }}??? $abil.TargetValue={{ $abil.TargetValue }}{{ end }})
|
|
||||||
{{- else if eq $abil.Target 19 -}}Rushing-Ahead({{ $abil.TargetValue }})
|
|
||||||
{{- else if eq $abil.Target 20 -}}Rushing-Behind({{ $abil.TargetValue }})
|
|
||||||
{{- else if eq $abil.Target 21 -}}Rushing-Style({{ if eq $abil.TargetValue 1 }}Front-Runner{{ else if eq $abil.TargetValue 2 }}Pace-Chaser{{ else if eq $abil.TargetValue 3 }}Late-Surger{{ else if eq $abil.TargetValue 4 }}End-Closer{{ else }}??? $abil.TargetValue={{ $abil.TargetValue }}{{ end }})
|
|
||||||
{{- end -}}
|
|
||||||
),
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
|
||||||
]),
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
|
||||||
], sp-cost = {{ $.SPCost -}}
|
|
||||||
, icon-id = {{ $.IconID -}}
|
|
||||||
)
|
|
||||||
{{- end -}}
|
|
||||||
|
|||||||
@@ -12,6 +12,21 @@ WITH skill_names AS (
|
|||||||
FROM skill_data d
|
FROM skill_data d
|
||||||
JOIN skill_names n ON d.id = n.id
|
JOIN skill_names n ON d.id = n.id
|
||||||
WHERE group_rate = 1
|
WHERE group_rate = 1
|
||||||
|
), card_name AS (
|
||||||
|
SELECT
|
||||||
|
"index" AS "id",
|
||||||
|
"text" AS "name"
|
||||||
|
FROM text_data n
|
||||||
|
WHERE category = 4
|
||||||
|
), card_unique AS (
|
||||||
|
SELECT DISTINCT
|
||||||
|
ss.skill_id1 AS unique_id,
|
||||||
|
card_name.id AS owner_id,
|
||||||
|
card_name.name
|
||||||
|
FROM card_data card
|
||||||
|
JOIN card_name ON card.id = card_name.id
|
||||||
|
JOIN card_rarity_data rd ON card.id = rd.card_id
|
||||||
|
JOIN skill_set ss ON rd.skill_set = ss.id
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
d.id,
|
d.id,
|
||||||
@@ -67,6 +82,8 @@ SELECT
|
|||||||
d.target_value_2_3,
|
d.target_value_2_3,
|
||||||
IFNULL(p.need_skill_point, 0) AS sp_cost,
|
IFNULL(p.need_skill_point, 0) AS sp_cost,
|
||||||
d.unique_skill_id_1,
|
d.unique_skill_id_1,
|
||||||
|
COALESCE(u.owner_id, iu.owner_id, 0) AS unique_owner_id,
|
||||||
|
COALESCE(u.name, iu.name, '') AS unique_owner,
|
||||||
d.icon_id,
|
d.icon_id,
|
||||||
ROW_NUMBER() OVER (ORDER BY d.id) - 1 AS "index"
|
ROW_NUMBER() OVER (ORDER BY d.id) - 1 AS "index"
|
||||||
FROM skill_data d
|
FROM skill_data d
|
||||||
@@ -74,4 +91,6 @@ FROM skill_data d
|
|||||||
LEFT JOIN skill_data ud ON d.unique_skill_id_1 = ud.id
|
LEFT JOIN skill_data ud ON d.unique_skill_id_1 = ud.id
|
||||||
LEFT JOIN skill_groups g ON d.group_id = g.group_id
|
LEFT JOIN skill_groups g ON d.group_id = g.group_id
|
||||||
LEFT JOIN single_mode_skill_need_point p ON d.id = p.id
|
LEFT JOIN single_mode_skill_need_point p ON d.id = p.id
|
||||||
|
LEFT JOIN card_unique u ON d.id = u.unique_id
|
||||||
|
LEFT JOIN card_unique iu ON d.unique_skill_id_1 = iu.unique_id
|
||||||
ORDER BY d.id
|
ORDER BY d.id
|
||||||
|
|||||||
Reference in New Issue
Block a user