Skip to content

Instantly share code, notes, and snippets.

@alpha123
Created May 5, 2023 13:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alpha123/0e0f54b0eba1516b3907dc0e2efcb968 to your computer and use it in GitHub Desktop.
Save alpha123/0e0f54b0eba1516b3907dc0e2efcb968 to your computer and use it in GitHub Desktop.
const enum Strategy { Nige, Senkou, Sasi, Oikomi, Oonige }
const enum Surface { Turf, Dirt }
const enum Aptitude { S, A, B, C, D, E, F, G }
type Phase = 0 | 1 | 2;
interface HorseParameters {
speed: number
stamina: number
power: number
guts: number
int: number
strategy: Strategy
distanceAptitude: Aptitude
surfaceAptitude: Aptitude
accelSkillModifier: number
}
interface CourseData {
distance: number
surface: Surface
}
const Speed = Object.freeze({
StrategyPhaseCoefficient: [
[1.0, 0.98, 0.962],
[0.978, 0.991, 0.975],
[0.938, 0.998, 0.994],
[0.931, 1.0, 1.0],
[1.063, 0.962, 0.95]
],
DistanceProficiencyModifier: [1.05, 1.0, 0.9, 0.8, 0.6, 0.4, 0.2, 0.1]
});
function baseSpeed(course: CourseData) {
return 20.0 - (course.distance - 2000) / 1000;
}
function baseTargetSpeed(horse: HorseParameters, course: CourseData, phase: Phase) {
return baseSpeed(course) * Speed.StrategyPhaseCoefficient[horse.strategy][phase] +
+(phase == 2) * Math.sqrt(500.0 * horse.speed) *
Speed.DistanceProficiencyModifier[horse.distanceAptitude] *
0.002;
}
function lastSpurtSpeed(horse: HorseParameters, course: CourseData) {
return (baseTargetSpeed(horse, course, 2) + 0.01 * baseSpeed(course)) * 1.05 +
Math.sqrt(500.0 * horse.speed) * Speed.DistanceProficiencyModifier[horse.distanceAptitude] * 0.002 +
Math.pow(450.0 * horse.guts, 0.597) * 0.0001;
}
const Acceleration = Object.freeze({
StrategyPhaseCoefficient: [
[1.0, 1.0, 0.996],
[0.985, 1.0, 0.996],
[0.975, 1.0, 1.0],
[0.945, 1.0, 0.997],
[1.17, 0.94, 0.956]
],
GroundTypeProficiencyModifier: [1.05, 1.0, 0.9, 0.8, 0.7, 0.5, 0.3, 0.1],
DistanceProficiencyModifier: [1.0, 1.0, 1.0, 1.0, 1.0, 0.6, 0.5, 0.4]
});
const BaseAccel = 0.0006;
const UphillBaseAccel = 0.0004;
function accel(baseAccel, horse: HorseParameters) {
return baseAccel * Math.sqrt(500.0 * horse.power) *
Acceleration.StrategyPhaseCoefficient[horse.strategy][2] *
Acceleration.GroundTypeProficiencyModifier[horse.surfaceAptitude] *
Acceleration.DistanceProficiencyModifier[horse.distanceAptitude] +
horse.accelSkillModifier;
}
function velocity(horse: HorseParameters, course: CourseData, t: number) {
return Math.min(accel(BaseAccel, horse) * t + baseTargetSpeed(horse, course, 1), lastSpurtSpeed(horse, course));
}
function uncappedVelocityIntegral(horse: HorseParameters, course: CourseData, t: number) {
const phase1Speed = baseTargetSpeed(horse, course, 1);
return Math.pow(t, 2) * accel(BaseAccel, horse) / 2 + phase1Speed * t;
}
function position(horse: HorseParameters, course: CourseData, t: number) {
const spurtStart = course.distance * 2/3;
const spurtSpeed = lastSpurtSpeed(horse, course);
const phase1Speed = baseTargetSpeed(horse, course, 1);
const accelTime = (spurtSpeed - phase1Speed) / accel(BaseAccel, horse);
if (t < accelTime) {
return uncappedVelocityIntegral(horse, course, t) + spurtStart;
} else {
const accelDistance = uncappedVelocityIntegral(horse, course, accelTime);
return spurtSpeed * (t - accelTime) + spurtStart + accelDistance;
}
}
function phase2Time(horse: HorseParameters, course: CourseData) {
// solve position(t) == course.distance
const spurtStart = course.distance * 2/3;
const spurtSpeed = lastSpurtSpeed(horse, course);
const phase1Speed = baseTargetSpeed(horse, course, 1);
const accelTime = (spurtSpeed - phase1Speed) / accel(BaseAccel, horse);
const accelDistance = uncappedVelocityIntegral(horse, course, accelTime);
return (course.distance - spurtStart - accelDistance) / spurtSpeed + accelTime;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment