all: remove koka code, move go to repo root

This commit is contained in:
2026-04-29 23:28:13 -04:00
parent 2cec7c5699
commit 0799bf658f
35 changed files with 4 additions and 1681 deletions

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "std"]
path = std
url = git@github.com:koka-community/std.git

View File

@@ -25,7 +25,7 @@ import (
"github.com/disgoorg/disgo/rest"
httpmiddle "github.com/go-chi/chi/v5/middleware"
"git.sunturtle.xyz/zephyr/horse/horse"
"git.sunturtle.xyz/zephyr/horse"
)
func main() {

View File

@@ -9,8 +9,8 @@ import (
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/handler"
"git.sunturtle.xyz/zephyr/horse"
"git.sunturtle.xyz/zephyr/horse/cmd/horsebot/autocomplete"
"git.sunturtle.xyz/zephyr/horse/horse"
)
type skillServer struct {

View File

@@ -20,7 +20,7 @@ import (
"zombiezen.com/go/sqlite"
"zombiezen.com/go/sqlite/sqlitex"
"git.sunturtle.xyz/zephyr/horse/horse"
"git.sunturtle.xyz/zephyr/horse"
)
func main() {

View File

@@ -1,8 +0,0 @@
#!/bin/sh
set -ex
go run ./horsegen "$@"
go generate ./horse/...
go fmt ./...
go test ./...

View File

@@ -1,6 +0,0 @@
# horse
This directory contains manually written code and types on which the generated code depends.
The generated code is in ./global; other regions will follow the same convention once they are supported.
It is always safe to delete the entire directories and regenerate them.

View File

@@ -1,17 +0,0 @@
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 ++ ")"

View File

@@ -1,80 +0,0 @@
module horse/game-id
// Game ID for characters, cards, skills, races, &c.
// Values for different categories may overlap.
pub 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.
pub struct scenario-id
game-id: game-id
// 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 uma-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
// Game ID for sparks,
// i.e. succession factors.
pub struct spark-id
game-id: game-id
// Game ID for spark groups,
// i.e. all rarities (star counts) of a single spark.
pub struct spark-group-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
// Construct an invalid game ID.
pub inline fun default/game-id(): game-id
0

View File

@@ -1,8 +0,0 @@
module horse/global
import horse/game-id
// Shared saddle affinity bonus.
// `s` should be the complete list of all saddles shared between the veterans.
pub fun saddle-bonus(s: list<saddle-id>): int
s.length

View File

@@ -1,124 +0,0 @@
module horse/legacy
import std/num/decimal
import std/data/linearmap
import std/data/linearset
import horse/game-id
import horse/spark
import horse/prob/dist
// A legacy, or parent and grandparents.
pub struct legacy
uma: veteran
sub1: veteran
sub2: veteran
// A veteran, or the result of a completed career.
pub struct veteran
uma: uma-id
sparks: list<spark-id>
saddles: list<saddle-id>
// Get all saddles shared between two lists thereof.
pub fun shared-saddles(a: list<saddle-id>, b: list<saddle-id>): list<saddle-id>
val sa: linearSet<saddle-id> = a.foldl(linear-set(Nil)) fn(s, id) if id.is-valid then s.add(id) else s
val c: linearSet<saddle-id> = b.foldl(linear-set(Nil)) fn(s, id) if sa.member(id) then s.add(id) else s
c.list
// Get the individual affinity for a legacy.
// Any invalid ID is treated as giving 0.
pub fun parent-affinity(
trainee: uma-id,
legacy: legacy,
other-parent: uma-id,
?character-id: (uma-id) -> character-id,
?saddle-bonus: (list<saddle-id>) -> int,
?pair-affinity: (a: character-id, b: character-id) -> int,
?trio-affinity: (a: character-id, b: character-id, c: character-id) -> int
): int
val t = trainee.character-id
val p1 = legacy.uma.uma.character-id
val s1 = legacy.sub1.uma.character-id
val s2 = legacy.sub2.uma.character-id
val p2 = other-parent.character-id
pair-affinity(t, p1) + pair-affinity(p1, p2)
+ trio-affinity(t, p1, s1) + trio-affinity(t, p1, s2)
+ saddle-bonus(shared-saddles(legacy.uma.saddles, legacy.sub1.saddles)) + saddle-bonus(shared-saddles(legacy.uma.saddles, legacy.sub2.saddles))
// Get the individual affinities for a legacy's sub-legacies.
// The first value is the legacy for the `legacy.sub1` and the second is for
// `legacy.sub2`.
// Any invalid ID is treated as giving 0.
pub fun sub-affinity(
trainee: uma-id,
legacy: legacy,
?character-id: (uma-id) -> character-id,
?saddle-bonus: (list<saddle-id>) -> int,
?trio-affinity: (a: character-id, b: character-id, c: character-id) -> int
): (int, int)
val t = trainee.character-id
val p = legacy.uma.uma.character-id
val s1 = legacy.sub1.uma.character-id
val s2 = legacy.sub2.uma.character-id
val r1 = trio-affinity(t, p, s1) + saddle-bonus(shared-saddles(legacy.uma.saddles, legacy.sub1.saddles))
val r2 = trio-affinity(t, p, s2) + saddle-bonus(shared-saddles(legacy.uma.saddles, legacy.sub2.saddles))
(r1, r2)
// Associate each spark with its actual chance to activate given an individual
// affinity value and the possible effects when it does.
pub fun uma/inspiration(l: list<spark-id>, affinity: int, ?spark-type: (spark-id) -> spark-type, ?rarity: (spark-id) -> rarity, ?effects: (spark-id) -> list<list<spark-effect>>): list<(spark-id, decimal, list<list<spark-effect>>)>
val a = decimal(1 + affinity, -2)
l.map() fn(id) (id, min(id.base-proc * a, 1.decimal), id.effects)
// Get the complete list of effects that may occur in an inspiration event
// and the respective probability of activation.
// Duplicates, i.e. multiple veterans with the same spark, are preserved.
pub fun inspiration(
trainee: uma-id,
parent1: legacy,
parent2: legacy,
?character-id: (uma-id) -> character-id,
?saddle-bonus: (list<saddle-id>) -> int,
?pair-affinity: (a: character-id, b: character-id) -> int,
?trio-affinity: (a: character-id, b: character-id, c: character-id) -> int,
?spark-type: (spark-id) -> spark-type,
?rarity: (spark-id) -> rarity,
?effects: (spark-id) -> list<list<spark-effect>>
): list<(spark-id, decimal, list<list<spark-effect>>)>
val p1a = parent-affinity(trainee, parent1, parent2.uma.uma)
val p2a = parent-affinity(trainee, parent2, parent1.uma.uma)
val (s11a, s12a) = sub-affinity(trainee, parent1)
val (s21a, s22a) = sub-affinity(trainee, parent2)
[
inspiration(parent1.uma.sparks, p1a),
inspiration(parent1.sub1.sparks, s11a),
inspiration(parent1.sub2.sparks, s12a),
inspiration(parent2.uma.sparks, p2a),
inspiration(parent2.sub1.sparks, s21a),
inspiration(parent2.sub2.sparks, s22a),
].concat
// Reduce a spark effect list to the skill it is able to give.
pub fun skills(l: list<list<spark-effect>>): maybe<skill-id>
val r: linearSet<skill-id> = l.head(Nil).foldl(linear-set(Nil)) fn(s, eff)
match eff
Skill-Hint(id, _) -> s + id
_ -> s
r.list.head
// Reduce a spark effect list to the aptitude it is able to give.
pub fun aptitudes(l: list<list<spark-effect>>): maybe<aptitude>
val r: linearSet<aptitude> = l.head(Nil).foldl(linear-set(Nil)) fn(s, eff)
match eff
Aptitude-Up(apt) -> s + apt
_ -> s
r.list.head
// Get the overall chance of each count of sparks, including zero, providing a
// given type of effect activating in a single inspiration event.
pub fun inspiration-gives(l: list<(spark-id, decimal, list<list<spark-effect>>)>, f: (list<list<spark-effect>>) -> maybe<a>, ?a/(==): (a, a) -> bool): linearMap<a, list<decimal>>
val m: linearMap<_, list<decimal>> = l.foldl(LinearMap(Nil)) fn(m, (_, p, eff))
match f(eff)
Nothing -> m
Just(a) -> m.map/update(a, [p]) fn(cur, pp) pp.append(cur)
m.map() fn(_, v) poisson-binomial(v)

View File

@@ -1,134 +0,0 @@
module horse/movement
// Surface types.
pub type surface
Turf
Dirt
// Automatically generated.
// Shows a string representation of the `surface` type.
pub fun surface/show(this : surface) : e string
match this
Turf -> "Turf"
Dirt -> "Dirt"
// Race distance types.
pub type distance
Sprint
Mile
Medium
Long
// Automatically generated.
// Shows a string representation of the `distance` type.
pub fun distance/show(this : distance) : e string
match this
Sprint -> "Sprint"
Mile -> "Mile"
Medium -> "Medium"
Long -> "Long"
// 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"
// Aptitude levels.
pub type aptitude-level
G
F
E
D
C
B
A
S
// Get the integer value for an aptitude level, starting at G -> 1.
pub fun aptitude-level/int(l: aptitude-level): int
match l
G -> 1
F -> 2
E -> 3
D -> 4
C -> 5
B -> 6
A -> 7
S -> 8
// Get the aptitude level corresponding to an integer, starting at 1 -> G.
pub fun int/aptitude-level(l: int): maybe<aptitude-level>
match l
1 -> Just(G)
2 -> Just(F)
3 -> Just(E)
4 -> Just(D)
5 -> Just(C)
6 -> Just(B)
7 -> Just(A)
8 -> Just(S)
_ -> Nothing
// Comparison of the `aptitude-level` type.
pub fun aptitude-level/cmp(this : aptitude-level, other : aptitude-level) : e order
cmp(this.int, other.int)
// Automatically generated.
// Fip comparison of the `aptitude-level` type.
pub fun aptitude-level/order2(this : aptitude-level, other : aptitude-level) : order2<aptitude-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 `aptitude-level` type.
pub fun aptitude-level/show(this : aptitude-level) : string
match this
G -> "G"
F -> "F"
E -> "E"
D -> "D"
C -> "C"
B -> "B"
A -> "A"
S -> "S"

View File

@@ -1,21 +0,0 @@
module horse/prob/dist
import std/num/decimal
tail fun pb-step(pn: list<decimal>, pi: decimal, pmfkm1: decimal, pmf: list<decimal>, next: ctx<list<decimal>>): list<decimal>
match pn
Nil -> next ++. Nil // final step overall
Cons(_, pp) -> match pmf
Cons(pmfk, pmf') ->
val next' = next ++ ctx Cons(pi * pmfkm1 + (1.decimal - pi) * pmfk, hole)
pb-step(pp, pi, pmfk, pmf', next')
Nil -> next ++. Cons(pi * pmfkm1, Nil) // last step of this iteration
// Given `n` different Bernoulli processes with respective probabilities in `pn`,
// find the distribution of `k` successes for `k` ranging from 0 to `n` inclusive.
// The index in the result list corresponds to `k`.
pub fun pmf/poisson-binomial(pn: list<decimal>): list<decimal>
pn.foldl([1.decimal]) fn(pmf, pi)
match pmf
Cons(pmf0, pmf') -> pb-step(pn, pi, pmf0, pmf', ctx Cons((1.decimal - pi) * pmf0, hole))
Nil -> impossible("fold started with non-empty pmf but got empty pmf")

View File

@@ -1,158 +0,0 @@
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

View File

@@ -1,58 +0,0 @@
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)

View File

@@ -1,301 +0,0 @@
module horse/race
import std/data/linearset
import horse/game-id
pub struct race-detail
race-id: race-id
name: string
grade: grade
thumbnail-id: race-thumbnail-id
// 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: race-id
pub fun detail(
r: race-id,
?race/show: (race-id) -> string,
?race/grade: (race-id) -> grade,
?race/thumbnail: (race-id) -> race-thumbnail-id,
?race/primary: (race-id) -> race-id
): race-detail
Race-detail(r, r.show, r.grade, r.thumbnail, r.primary)
pub fun race-detail/show(r: race-detail): string
val Race-detail(Race-id(id), name) = r
name ++ " (ID " ++ id.show ++ ")"
// Race grades.
pub type grade
Pre-OP
OP
G3
G2
G1
EX
// Automatically generated.
// Comparison of the `grade` type.
pub fun grade/cmp(this : grade, other : grade) : e order
match (this, other)
(Pre-OP, Pre-OP) -> Eq
(Pre-OP, _) -> Lt
(_, Pre-OP) -> Gt
(OP, OP) -> Eq
(OP, _) -> Lt
(_, OP) -> Gt
(G3, G3) -> Eq
(G3, _) -> Lt
(_, G3) -> Gt
(G2, G2) -> Eq
(G2, _) -> Lt
(_, G2) -> Gt
(G1, G1) -> Eq
(G1, _) -> Lt
(_, G1) -> Gt
(EX, EX) -> Eq
// Automatically generated.
// Shows a string representation of the `grade` type.
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)
(Honor, Honor) -> True
(G3-Win, G3-Win) -> True
(G2-Win, G2-Win) -> True
(G1-Win, G1-Win) -> True
(_, _) -> False
// Turn that a race occurred.
pub struct turn
year: turn-year
month: turn-month
half: turn-half
// Automatically generated.
// Equality comparison of the `turn` type.
pub fun turn/(==)(this : turn, other : turn) : e bool
match (this, other)
(Turn(year, month, half), Turn(year', month', half')) -> year == year' && month == month' && half == half'
// Automatically generated.
// Fip comparison of the `turn` type.
pub fun turn/order2(this : turn, other : turn) : e order2<turn>
match (this, other)
(Turn(year, month, half), Turn(year', month', half')) ->
match year.order2(year')
Eq2(year_eq) ->
match month.order2(month')
Eq2(month_eq) ->
match half.order2(half')
Eq2(half_eq) -> Eq2(Turn(year_eq, month_eq, half_eq))
Lt2(half_lt, half_gt) -> Lt2(Turn(year_eq, month_eq, half_lt), Turn(year_eq, month_eq, half_gt))
Gt2(half_lt, half_gt) -> Gt2(Turn(year_eq, month_eq, half_lt), Turn(year_eq, month_eq, half_gt))
Lt2(month_lt, month_gt) -> Lt2(Turn(year_eq, month_lt, half), Turn(year_eq, month_gt, half'))
Gt2(month_lt, month_gt) -> Gt2(Turn(year_eq, month_lt, half'), Turn(year_eq, month_gt, half))
Lt2(year_lt, year_gt) -> Lt2(Turn(year_lt, month, half), Turn(year_gt, month', half'))
Gt2(year_lt, year_gt) -> Gt2(Turn(year_lt, month', half'), Turn(year_gt, month, half))
// Automatically generated.
// Shows a string representation of the `turn` type.
pub fun turn/show(this : turn) : e string
this.year.show ++ " " ++ this.half.show ++ " " ++ this.month.show
pub type turn-year
Junior
Classic
Senior
Finale
// Automatically generated.
// Equality comparison of the `turn-year` type.
pub fun turn-year/(==)(this : turn-year, other : turn-year) : e bool
match (this, other)
(Junior, Junior) -> True
(Classic, Classic) -> True
(Senior, Senior) -> True
(Finale, Finale) -> True
(_, _) -> False
// Automatically generated.
// Fip comparison of the `turn-year` type.
pub fun turn-year/order2(this : turn-year, other : turn-year) : e order2<turn-year>
match (this, other)
(Junior, Junior) -> Eq2(Junior)
(Junior, other') -> Lt2(Junior, other')
(this', Junior) -> Gt2(Junior, this')
(Classic, Classic) -> Eq2(Classic)
(Classic, other') -> Lt2(Classic, other')
(this', Classic) -> Gt2(Classic, this')
(Senior, Senior) -> Eq2(Senior)
(Senior, other') -> Lt2(Senior, other')
(this', Senior) -> Gt2(Senior, this')
(Finale, Finale) -> Eq2(Finale)
// Automatically generated.
// Shows a string representation of the `turn-year` type.
pub fun turn-year/show(this : turn-year) : e string
match this
Junior -> "Junior Year"
Classic -> "Classic Year"
Senior -> "Senior Year"
Finale -> "Finale 1" // the 1 is in the game
pub type turn-month
January
February
March
April
May
June
July
August
September
November
December
// Automatically generated.
// Equality comparison of the `turn-month` type.
pub fun turn-month/(==)(this : turn-month, other : turn-month) : e bool
match (this, other)
(January, January) -> True
(February, February) -> True
(March, March) -> True
(April, April) -> True
(May, May) -> True
(June, June) -> True
(July, July) -> True
(August, August) -> True
(September, September) -> True
(November, November) -> True
(December, December) -> True
(_, _) -> False
// Automatically generated.
// Fip comparison of the `turn-month` type.
pub fun turn-month/order2(this : turn-month, other : turn-month) : e order2<turn-month>
match (this, other)
(January, January) -> Eq2(January)
(January, other') -> Lt2(January, other')
(this', January) -> Gt2(January, this')
(February, February) -> Eq2(February)
(February, other') -> Lt2(February, other')
(this', February) -> Gt2(February, this')
(March, March) -> Eq2(March)
(March, other') -> Lt2(March, other')
(this', March) -> Gt2(March, this')
(April, April) -> Eq2(April)
(April, other') -> Lt2(April, other')
(this', April) -> Gt2(April, this')
(May, May) -> Eq2(May)
(May, other') -> Lt2(May, other')
(this', May) -> Gt2(May, this')
(June, June) -> Eq2(June)
(June, other') -> Lt2(June, other')
(this', June) -> Gt2(June, this')
(July, July) -> Eq2(July)
(July, other') -> Lt2(July, other')
(this', July) -> Gt2(July, this')
(August, August) -> Eq2(August)
(August, other') -> Lt2(August, other')
(this', August) -> Gt2(August, this')
(September, September) -> Eq2(September)
(September, other') -> Lt2(September, other')
(this', September) -> Gt2(September, this')
(November, November) -> Eq2(November)
(November, other') -> Lt2(November, other')
(this', November) -> Gt2(November, this')
(December, December) -> Eq2(December)
// Automatically generated.
// Shows a string representation of the `turn-month` type.
pub fun turn-month/show(this : turn-month) : e string
match this
January -> "January"
February -> "February"
March -> "March"
April -> "April"
May -> "May"
June -> "June"
July -> "July"
August -> "August"
September -> "September"
November -> "November"
December -> "December"
pub type turn-half
Early
Late
// Automatically generated.
// Equality comparison of the `turn-half` type.
pub fun turn-half/(==)(this : turn-half, other : turn-half) : e bool
match (this, other)
(Early, Early) -> True
(Late, Late) -> True
(_, _) -> False
// Automatically generated.
// Fip comparison of the `turn-half` type.
pub fun turn-half/order2(this : turn-half, other : turn-half) : e order2<turn-half>
match (this, other)
(Early, Early) -> Eq2(Early)
(Early, other') -> Lt2(Early, other')
(this', Early) -> Gt2(Early, this')
(Late, Late) -> Eq2(Late)
// Automatically generated.
// Shows a string representation of the `turn-half` type.
pub fun turn-half/show(this : turn-half) : e string
match this
Early -> "Early"
Late -> "Late"

View File

@@ -1,249 +0,0 @@
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<uma-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<uma-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, ?uma/show: (uma-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 Uma 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
dur-scale: dur-scale
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, Direct-Dur, cooldown, abilities) | cooldown >= 500.decimal -> condition ++ " -> for " ++ duration.show ++ "s, " ++ abilities.show
Activation("", condition, duration, dur-scale, cooldown, abilities) | cooldown >= 500.decimal -> condition ++ " -> for " ++ duration.show ++ "s " ++ dur-scale.show ++ ", " ++ abilities.show
Activation("", condition, duration, Direct-Dur, cooldown, abilities) -> condition ++ " -> for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
Activation("", condition, duration, dur-scale, cooldown, abilities) -> condition ++ " -> for " ++ duration.show ++ "s " ++ dur-scale.show ++ " on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
Activation(precondition, condition, duration, _, _, abilities) | !duration.is-pos -> precondition ++ " -> " ++ condition ++ " -> " ++ abilities.show
Activation(precondition, condition, duration, Direct-Dur, cooldown, abilities) | cooldown >= 500.decimal -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s, " ++ abilities.show
Activation(precondition, condition, duration, dur-scale, cooldown, abilities) | cooldown >= 500.decimal -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s " ++ dur-scale.show ++ ", " ++ abilities.show
Activation(precondition, condition, duration, Direct-Dur, cooldown, abilities) -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
Activation(precondition, condition, duration, dur-scale, cooldown, abilities) -> precondition ++ " -> " ++ condition ++ " -> for " ++ duration.show ++ "s " ++ dur-scale.show ++ " on " ++ cooldown.show ++ "s cooldown, " ++ abilities.show
// Special scaling types for skill activation durations.
pub type dur-scale
Direct-Dur
Front-Distance-Dur
Multiply-Remaining-HP
Increment-Pass
Midrace-Side-Block-Time-Dur
Multiply-Remaining-HP2
pub fun dur-scale/show(s: dur-scale): string
match s
Direct-Dur -> "with no scaling"
Front-Distance-Dur -> "scaling with distance from the front"
Multiply-Remaining-HP -> "scaling with remaining HP"
Increment-Pass -> "increasing with each pass while active"
Midrace-Side-Block-Time-Dur -> "scaling with mid-race phase blocked side time"
Multiply-Remaining-HP2 -> "scaling with remaining HP"
// 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"

View File

@@ -1,175 +0,0 @@
module horse/spark
import std/num/decimal
import horse/game-id
import horse/movement
// A spark on a veteran.
pub struct spark-detail
spark-id: spark-id
typ: spark-type
rarity: rarity
pub fun detail(id: spark-id, ?spark/spark-type: (spark-id) -> spark-type, ?spark/rarity: (spark-id) -> rarity): spark-detail
Spark-detail(id, id.spark-type, id.rarity)
pub fun spark-detail/show(s: spark-detail, ?spark/show: (spark-id) -> string): string
s.spark-id.show ++ " " ++ "\u2605".repeat(s.rarity.int)
// The category of a spark; roughly, blue, pink, green, or white, with some
// further subdivisions.
pub type spark-type
Stat // blue
Aptitude // red/pink
Unique // green
Race
Skill
// skip Carnival Bonus
Scenario
Surface
Distance
Style
Hidden
// Spark targets and effects.
pub type spark-effect
Stat-Up(s: stat, amount: int)
SP-Up(amount: int)
// skip Carnival Bonus
Random-Stat-Up(amount: int)
Aptitude-Up(a: aptitude, amount: int)
Skill-Hint(s: skill-id, levels: int)
Stat-Cap-Up(s: stat, amount: int)
// Get the base probability for a spark to trigger during a single inheritance.
pub fun decimal/base-proc(id: spark-id, ?spark-type: (spark-id) -> spark-type, ?rarity: (spark-id) -> rarity): decimal
val t = id.spark-type
val r = id.rarity
match (t, r)
(Stat, One) -> 70.decimal(-2)
(Stat, Two) -> 80.decimal(-2)
(Stat, Three) -> 90.decimal(-2)
(Aptitude, One) -> 1.decimal(-2)
(Aptitude, Two) -> 3.decimal(-2)
(Aptitude, Three) -> 5.decimal(-2)
(Unique, One) -> 5.decimal(-2)
(Unique, Two) -> 10.decimal(-2)
(Unique, Three) -> 15.decimal(-2)
(Race, One) -> 1.decimal(-2)
(Race, Two) -> 2.decimal(-2)
(Race, Three) -> 3.decimal(-2)
(_, One) -> 3.decimal(-2)
(_, Two) -> 6.decimal(-2)
(_, Three) -> 9.decimal(-2)
// The level or star count of a spark.
pub type rarity
One
Two
Three
pub fun rarity/int(l: rarity): int
match l
One -> 1
Two -> 2
Three -> 3
pub fun rarity/show(l: rarity): string
match l
One -> "1"
Two -> "2"
Three -> "3"
// Stat (blue) spark.
pub type stat
Speed
Stamina
Power
Guts
Wit
// Automatically generated.
// Shows a string representation of the `stat` type.
pub fun stat/show(this : stat) : e string
match this
Speed -> "Speed"
Stamina -> "Stamina"
Power -> "Power"
Guts -> "Guts"
Wit -> "Wit"
// Aptitude (red/pink) spark.
pub type aptitude
Turf
Dirt
Sprint
Mile
Medium
Long
Front-Runner
Pace-Chaser
Late-Surger
End-Closer
// Automatically generated.
// Fip comparison of the `aptitude` type.
pub fun aptitude/order2(this : aptitude, other : aptitude) : e order2<aptitude>
match (this, other)
(Turf, Turf) -> Eq2(Turf)
(Turf, other') -> Lt2(Turf, other')
(this', Turf) -> Gt2(Turf, this')
(Dirt, Dirt) -> Eq2(Dirt)
(Dirt, other') -> Lt2(Dirt, other')
(this', Dirt) -> Gt2(Dirt, this')
(Sprint, Sprint) -> Eq2(Sprint)
(Sprint, other') -> Lt2(Sprint, other')
(this', Sprint) -> Gt2(Sprint, this')
(Mile, Mile) -> Eq2(Mile)
(Mile, other') -> Lt2(Mile, other')
(this', Mile) -> Gt2(Mile, this')
(Medium, Medium) -> Eq2(Medium)
(Medium, other') -> Lt2(Medium, other')
(this', Medium) -> Gt2(Medium, this')
(Long, Long) -> Eq2(Long)
(Long, other') -> Lt2(Long, other')
(this', Long) -> Gt2(Long, this')
(Front-Runner, Front-Runner) -> Eq2(Front-Runner)
(Front-Runner, other') -> Lt2(Front-Runner, other')
(this', Front-Runner) -> Gt2(Front-Runner, this')
(Pace-Chaser, Pace-Chaser) -> Eq2(Pace-Chaser)
(Pace-Chaser, other') -> Lt2(Pace-Chaser, other')
(this', Pace-Chaser) -> Gt2(Pace-Chaser, this')
(Late-Surger, Late-Surger) -> Eq2(Late-Surger)
(Late-Surger, other') -> Lt2(Late-Surger, other')
(this', Late-Surger) -> Gt2(Late-Surger, this')
(End-Closer, End-Closer) -> Eq2(End-Closer)
// Automatically generated.
// Equality comparison of the `aptitude` type.
pub fun aptitude/(==)(this : aptitude, other : aptitude) : e bool
match (this, other)
(Turf, Turf) -> True
(Dirt, Dirt) -> True
(Sprint, Sprint) -> True
(Mile, Mile) -> True
(Medium, Medium) -> True
(Long, Long) -> True
(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 `aptitude` type.
pub fun aptitude/show(this : aptitude): string
match this
Turf -> "Turf"
Dirt -> "Dirt"
Sprint -> "Sprint"
Mile -> "Mile"
Medium -> "Medium"
Long -> "Long"
Front-Runner -> "Front Runner"
Pace-Chaser -> "Pace Chaser"
Late-Surger -> "Late Surger"
End-Closer -> "End Closer"

View File

@@ -1,27 +0,0 @@
module horse/uma
import horse/game-id
import horse/movement
// Details of an uma, or character card.
pub struct uma-detail
uma-id: uma-id
character-id: character-id
sprint: aptitude-level
mile: aptitude-level
medium: aptitude-level
long: aptitude-level
front-runner: aptitude-level
pace-chaser: aptitude-level
late-surger: aptitude-level
end-closer: aptitude-level
turf: aptitude-level
dirt: aptitude-level
unique: skill-id
skill1: skill-id
skill2: skill-id
skill3: skill-id
skill-pl2: skill-id
skill-pl3: skill-id
skill-pl4: skill-id
skill-pl5: skill-id

View File

@@ -3,7 +3,7 @@ package horse_test
import (
"testing"
"git.sunturtle.xyz/zephyr/horse/horse"
"git.sunturtle.xyz/zephyr/horse"
)
func TestTenThousandthsString(t *testing.T) {

1
std

Submodule std deleted from 41b8aed39e

View File

@@ -1,295 +0,0 @@
module test/example
import std/num/decimal
import std/data/linearmap
import horse/game-id
import horse/global
import horse/global/character
import horse/global/saddle
import horse/global/skill
import horse/global/spark
import horse/global/uma
import horse/legacy
val p1 = Legacy(
uma = Veteran(
uma = Uma-id(102001), // seiun sky
sparks = [
301, // 1* power
2102, // 2* front runner
10200103, // 3* angling and scheming
1000302, // 2* osaka hai
1001001, // 1* japanese derby
1001101, // 1* yasuda kinen
1001701, // 1* qe2
2001402, // 2* non-standard distance
2004301, // 1* focus
2005301, // 1* early lead
2012401, // 1* front runner straightaways
2012502, // 2* front runner corners
2015201, // 1* front runner savvy
2016001, // 1* groundwork
2016102, // 2* thh
2016402, // 2* lone wolf
3000201, // 1* unity cup
].map(Spark-id(_)),
saddles = [
1, // classic triple crown
2, // senior autumn triple crown
4, // senior spring triple crown
5, // tenno sweep
6, // dual grand prix
7, // dual miles
10, // arima kinen
11, // japan cup
12, // derby
13, // tss
14, // takarazuka kinen
15, // tsa
16, // kikuka sho
17, // osaka hai
18, // satsuki sho
21, // yasuda kinen
23, // mile championship
25, // victoria mile
26, // qe2
33, // asahi hai fs
34, // hopeful stakes
96, // mainichi hai
].map(Saddle-id(_))
),
sub1 = Veteran(
uma = Uma-id(102601), // mihono bourbon
sparks = [
302, // 2* power
3303, // 3* medium
10260102, // 2* g00 1st
1001201, // 1* takarazuka kinen
1001702, // 2* qe2
1001901, // 1* japan cup
2004302, // 2* focus
2004502, // 2* prudent positioning
2012502, // 2* front corners
2015202, // 2* front savvy
2016002, // 2* groundwork
2016401, // 1* lone wolf
3000201, // 1* unity cup
].map(Spark-id(_)),
saddles = [
2, // senior autumn triple crown
6, // dual grand prix
7, // dual miles
10, // arima kinen
11, // japan cup
12, // derby
14, // takarazuka kinen
15, // tsa
17, // osaka hai
18, // satsuki sho
21, // yasuda kinen
23, // mile championship
25, // victoria mile
26, // qe2
27, // nhk mile cup
33, // asahi hai fs
34, // hopeful stakes
49, // spring stakes
].map(Saddle-id(_))
),
sub2 = Veteran(
uma = Uma-id(102401), // mayano top gun
sparks = [
302, // 2* power
1103, // 3* turf
10240101, // 1* flashy landing
1000601, // 1* tss
1001202, // 2* takarazuka kinen
1001502, // 2* kikuka sho
1001601, // 1* tsa
1002102, // 2* hanshin jf
1002301, // 1* arima kinen
2003503, // 3* corner recovery
2003802, // 2* straightaway recovery
2004602, // 2* ramp up
2005502, // 2* final push
2012702, // 2* leader's pride
2016002, // 2* groundwork
3000102, // 2* ura finale
].map(Spark-id(_)),
saddles = [
1, // classic triple crown
2, // senior autumn triple crown
4, // senior spring triple crown
5, // tenno sweep
6, // dual grand prix
7, // dual miles
10, // arima kinen
11, // japan cup
12, // derby
13, // tss
14, // takarazuka kinen
15, // tsa
16, // kikuka sho
18, // satsuki sho
21, // yasuda kinen
23, // mile championship
25, // victoria mile
26, // qe2
34, // hopeful stakes
35, // hanshin jf
].map(Saddle-id(_))
)
)
val p2 = Legacy(
uma = Veteran(
uma = Uma-id(102601), // mihono bourbon
sparks = [
302,
3303,
1001201,
1001702,
1001901,
2004302,
2004502,
2012502,
2015202,
2016002,
2016401,
3000201,
10260102,
].map(Spark-id(_)),
saddles = [
2,
6,
7,
10,
11,
12,
14,
15,
17,
18,
21,
23,
25,
26,
27,
33,
34,
49,
].map(Saddle-id(_))
),
sub1 = Veteran(
uma = Uma-id(102402), // wedding mayano
sparks = [
203,
3202,
1000701,
1000802,
1001201,
1001803,
2003502,
2003701,
2004301,
2005502,
2012401,
2016402,
10240202,
].map(Spark-id(_)),
saddles = [
1,
2,
6,
7,
10,
11,
12,
14,
15,
16,
18,
21,
23,
25,
26,
27,
33,
34,
48,
].map(Saddle-id(_))
),
sub2 = Veteran(
uma = Uma-id(100201), // silence suzuka
sparks = [
203,
1101,
1001901,
1002203,
1002302,
2000101,
2000201,
2001902,
2003501,
2005401,
2016001,
3000102,
10020101,
].map(Spark-id(_)),
saddles = [
2,
6,
10,
11,
12,
14,
15,
17,
18,
21,
25,
26,
27,
33,
34,
40,
42,
44,
45,
46,
49,
59,
61,
63,
65,
111,
113,
117,
126,
].map(Saddle-id(_))
)
)
val trainee = Uma-id(104601) // smart falcon
pub fun main()
val p1a = parent-affinity(trainee, p1, p2.uma.uma)
val p2a = parent-affinity(trainee, p2, p1.uma.uma)
val (s11a, s12a) = sub-affinity(trainee, p1)
val (s21a, s22a) = sub-affinity(trainee, p2)
println("trainee: " ++ trainee.show)
println("p1: " ++ p1.uma.uma.show ++ " affinity " ++ p1a.show)
println("s1-1: " ++ p1.sub1.uma.show ++ " affinity " ++ s11a.show)
println("s1-2: " ++ p1.sub2.uma.show ++ " affinity " ++ s12a.show)
println("p2: " ++ p2.uma.uma.show ++ " affinity " ++ p1a.show)
println("s1-1: " ++ p2.sub1.uma.show ++ " affinity " ++ s21a.show)
println("s1-2: " ++ p2.sub2.uma.show ++ " affinity " ++ s22a.show)
val inspo = inspiration(trainee, p1, p2)
val s = inspiration-gives(inspo, legacy/skills)
val a = inspiration-gives(inspo, legacy/aptitudes)
println("\nskills:")
s.list.foreach() fn((skill, pmf))
println(" " ++ skill.show ++ ": " ++ pmf.show)
println("\naptitudes:")
a.list.foreach() fn((apt, pmf))
println(" " ++ apt.show ++ ": " ++ pmf.show)

View File

@@ -1,12 +0,0 @@
module test/global
import horse/global/character
import horse/global/race
import horse/global/saddle
import horse/global/scenario
import horse/global/skill
import horse/global/spark
import horse/global/uma
pub fun main()
()