zenno: use a real last spurt phase
This commit is contained in:
+38
-38
@@ -8,11 +8,11 @@ import { binomPMF } from './prob';
|
||||
* Fundamental stats of umas.
|
||||
*/
|
||||
export enum Stat {
|
||||
Speed,
|
||||
Stamina,
|
||||
Power,
|
||||
Guts,
|
||||
Wit,
|
||||
Speed = 1,
|
||||
Stamina = 2,
|
||||
Power = 3,
|
||||
Guts = 4,
|
||||
Wit = 5,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,14 +118,15 @@ export function distance(raceLen: number): Distance {
|
||||
/**
|
||||
* Get the distances at which each phase of a race ends.
|
||||
* @param raceLen Length of the race in meters
|
||||
* @returns Ends of each phase in meters
|
||||
* @returns Ends of each phase in meters, including separate late and spurt phases
|
||||
*/
|
||||
export function phases(raceLen: number) {
|
||||
const sixth = raceLen / 6;
|
||||
return {
|
||||
[Phase.EarlyRace]: sixth,
|
||||
[Phase.MidRace]: 4 * sixth,
|
||||
[Phase.LateRace]: raceLen,
|
||||
[Phase.LateRace]: 5 * sixth,
|
||||
[Phase.LastSpurt]: raceLen,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -133,18 +134,18 @@ export function phases(raceLen: number) {
|
||||
* Race surfaces.
|
||||
*/
|
||||
export enum Surface {
|
||||
Turf,
|
||||
Dirt,
|
||||
Turf = 1,
|
||||
Dirt = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* Race ground condition types.
|
||||
*/
|
||||
export enum GroundConditions {
|
||||
Firm,
|
||||
Good,
|
||||
Soft,
|
||||
Heavy,
|
||||
Firm = 1,
|
||||
Good = 2,
|
||||
Soft = 3,
|
||||
Heavy = 4,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,12 +328,12 @@ export const RUNNING_STYLES = [
|
||||
|
||||
/**
|
||||
* Race phases.
|
||||
* While last spurt phase is also a phase, it is not distinguished here.
|
||||
*/
|
||||
export enum Phase {
|
||||
EarlyRace,
|
||||
MidRace,
|
||||
LateRace,
|
||||
EarlyRace = 0,
|
||||
MidRace = 1,
|
||||
LateRace = 2,
|
||||
LastSpurt = 3,
|
||||
}
|
||||
|
||||
const hpStrategyCoeff = {
|
||||
@@ -407,7 +408,7 @@ export function hpPerSecond(
|
||||
const pdmMod = pdm ? 0.6 : 1;
|
||||
const damMod = dam ? 0.4 : 1;
|
||||
const groundMod = groundHPRateMod[surface][conditions];
|
||||
const gutsMod = phase === Phase.LateRace ? 1 + 200 / (math.sqrt(600 * gutsStat) as number) : 1;
|
||||
const gutsMod = phase >= Phase.LateRace ? 1 + 200 / (math.sqrt(600 * gutsStat) as number) : 1;
|
||||
const sp = currentSpeed - baseSpeed(raceLen) + 12;
|
||||
return (20 / 144) * sp * sp * rushedMod * pdmMod * damMod * groundMod * gutsMod;
|
||||
}
|
||||
@@ -447,11 +448,11 @@ export function baseSpeed(raceLen: number): number {
|
||||
}
|
||||
|
||||
const speedStrategyPhaseCoeff = [
|
||||
[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],
|
||||
[1.0, 0.98, 0.962, 0.962],
|
||||
[0.978, 0.991, 0.975, 0.975],
|
||||
[0.938, 0.998, 0.994, 0.994],
|
||||
[0.931, 1.0, 1.0, 1.0],
|
||||
[1.063, 0.962, 0.95, 0.95],
|
||||
] as const;
|
||||
|
||||
const distanceProficiencyMod: Readonly<Record<AptitudeLevel, number>> = {
|
||||
@@ -471,7 +472,7 @@ const distanceProficiencyMod: Readonly<Record<AptitudeLevel, number>> = {
|
||||
* @param style Horse's running style
|
||||
* @param phase Phase to calculate for
|
||||
*/
|
||||
export function baseTargetSpeed(raceLen: number, style: RunningStyle, phase: Exclude<Phase, Phase.LateRace>): number;
|
||||
export function baseTargetSpeed(raceLen: number, style: RunningStyle, phase: Exclude<Phase, Phase.LateRace | Phase.LastSpurt>): number;
|
||||
/**
|
||||
* Get a horse's base target speed when not spurting during late race.
|
||||
* @param raceLen Length of the race in meters
|
||||
@@ -483,7 +484,7 @@ export function baseTargetSpeed(raceLen: number, style: RunningStyle, phase: Exc
|
||||
export function baseTargetSpeed(
|
||||
raceLen: number,
|
||||
style: RunningStyle,
|
||||
phase: Phase.LateRace,
|
||||
phase: Phase.LateRace | Phase.LastSpurt,
|
||||
speedStat: number,
|
||||
distanceApt: AptitudeLevel,
|
||||
): number;
|
||||
@@ -497,7 +498,7 @@ export function baseTargetSpeed(
|
||||
const base = baseSpeed(raceLen);
|
||||
const baseTarget = base * speedStrategyPhaseCoeff[style][phase];
|
||||
const late =
|
||||
phase === Phase.LateRace ? (math.sqrt(500 * speedStat!) as number) * distanceProficiencyMod[distanceApt!] * 0.002 : 0;
|
||||
phase >= Phase.LateRace ? (math.sqrt(500 * speedStat!) as number) * distanceProficiencyMod[distanceApt!] * 0.002 : 0;
|
||||
return baseTarget + late;
|
||||
}
|
||||
|
||||
@@ -512,7 +513,7 @@ export function sectionSpeed(
|
||||
raceLen: number,
|
||||
witStat: number,
|
||||
style: RunningStyle,
|
||||
phase: Exclude<Phase, Phase.LateRace>,
|
||||
phase: Exclude<Phase, Phase.LateRace | Phase.LastSpurt>,
|
||||
): [number, number];
|
||||
/**
|
||||
* Calculate the range of section speed values for a horse not spurting during late race.
|
||||
@@ -529,7 +530,7 @@ export function sectionSpeed(
|
||||
witStat: number,
|
||||
style: RunningStyle,
|
||||
distance: AptitudeLevel,
|
||||
phase: Phase.LateRace,
|
||||
phase: Phase.LateRace | Phase.LastSpurt,
|
||||
): [number, number];
|
||||
export function sectionSpeed(
|
||||
raceLen: number,
|
||||
@@ -537,7 +538,7 @@ export function sectionSpeed(
|
||||
witStatOrStyle: number | RunningStyle,
|
||||
styleOrPhase: RunningStyle | Phase,
|
||||
distance?: AptitudeLevel,
|
||||
lateRace?: Phase.LateRace,
|
||||
lateRace?: Phase.LateRace | Phase.LastSpurt,
|
||||
): [number, number] {
|
||||
const speedStat = lateRace !== undefined ? speedStatOrWitStat : 0;
|
||||
const witStat = lateRace !== undefined ? witStatOrStyle : speedStatOrWitStat;
|
||||
@@ -546,7 +547,7 @@ export function sectionSpeed(
|
||||
const base = baseSpeed(raceLen);
|
||||
const baseTarget = base * speedStrategyPhaseCoeff[style][phase];
|
||||
const late =
|
||||
phase === Phase.LateRace
|
||||
phase >= Phase.LateRace
|
||||
? (math.sqrt(500 * speedStat) as number) * distanceProficiencyMod[distance ?? AptitudeLevel.A] * 0.002
|
||||
: 0;
|
||||
const u = (witStat / 550000) * math.log10(witStat * 0.1);
|
||||
@@ -620,11 +621,11 @@ export const COURSE_WIDTH = 11.25;
|
||||
export const LANE_WIDTH = COURSE_WIDTH / 18;
|
||||
|
||||
const accelStrategyPhaseCoeff = {
|
||||
[RunningStyle.FrontRunner]: [1.0, 1.0, 0.996],
|
||||
[RunningStyle.PaceChaser]: [0.985, 1.0, 0.996],
|
||||
[RunningStyle.LateSurger]: [0.975, 1.0, 1.0],
|
||||
[RunningStyle.EndCloser]: [0.945, 1.0, 0.997],
|
||||
[RunningStyle.Runaway]: [1.17, 0.94, 0.956],
|
||||
[RunningStyle.FrontRunner]: [1.0, 1.0, 0.996, 0.996],
|
||||
[RunningStyle.PaceChaser]: [0.985, 1.0, 0.996, 0.996],
|
||||
[RunningStyle.LateSurger]: [0.975, 1.0, 1.0, 1.0],
|
||||
[RunningStyle.EndCloser]: [0.945, 1.0, 0.997, 0.997],
|
||||
[RunningStyle.Runaway]: [1.17, 0.94, 0.956, 0.956],
|
||||
} as const;
|
||||
|
||||
const surfaceProficiencyMod: Readonly<Record<AptitudeLevel, number>> = {
|
||||
@@ -681,6 +682,7 @@ const phaseDecel = {
|
||||
[Phase.EarlyRace]: -1.2,
|
||||
[Phase.MidRace]: -0.8,
|
||||
[Phase.LateRace]: -1.0,
|
||||
[Phase.LastSpurt]: -1.0,
|
||||
} as const;
|
||||
|
||||
/**
|
||||
@@ -695,9 +697,7 @@ export function deceleration(phase: Phase, pdm?: boolean, dead?: boolean): numbe
|
||||
return -1.2;
|
||||
}
|
||||
if (pdm) {
|
||||
// This isn't until 1.5anni.
|
||||
// return -0.5;
|
||||
return phaseDecel[phase];
|
||||
return -0.5;
|
||||
}
|
||||
return phaseDecel[phase];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user