zenno: rename Great Escape -> Runaway everywhere

Fixes #26.
This commit is contained in:
2026-07-19 15:38:01 -04:00
parent 2c1b4b9261
commit 74c22c7313
6 changed files with 64 additions and 66 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ const styleMap = {
Sentou: RunningStyle.PaceChaser, Sentou: RunningStyle.PaceChaser,
Sasi: RunningStyle.LateSurger, Sasi: RunningStyle.LateSurger,
Oikomi: RunningStyle.EndCloser, Oikomi: RunningStyle.EndCloser,
Oonige: RunningStyle.GreatEscape, Oonige: RunningStyle.Runaway,
} as const; } as const;
export interface ImportUma { export interface ImportUma {
+6 -6
View File
@@ -260,7 +260,7 @@ export function finalStat(adjStat: number, skillPassive: number): number {
/** /**
* Running styles for strategyphase coefficients. * Running styles for strategyphase coefficients.
* Great Escape is distinguished as a separate style even though it is * Runaway is distinguished as a separate style even though it is
* mechanically identical to Front Runner. * mechanically identical to Front Runner.
*/ */
export enum RunningStyle { export enum RunningStyle {
@@ -268,7 +268,7 @@ export enum RunningStyle {
PaceChaser, PaceChaser,
LateSurger, LateSurger,
EndCloser, EndCloser,
GreatEscape, Runaway,
} }
/** /**
@@ -279,7 +279,7 @@ export const RUNNING_STYLES = [
['Pace Chaser', RunningStyle.PaceChaser], ['Pace Chaser', RunningStyle.PaceChaser],
['Late Surger', RunningStyle.LateSurger], ['Late Surger', RunningStyle.LateSurger],
['End Closer', RunningStyle.EndCloser], ['End Closer', RunningStyle.EndCloser],
['Great Escape', RunningStyle.GreatEscape], ['Runaway', RunningStyle.Runaway],
] as const; ] as const;
/** /**
@@ -325,7 +325,7 @@ const hpStrategyCoeff = {
[RunningStyle.PaceChaser]: 0.89, [RunningStyle.PaceChaser]: 0.89,
[RunningStyle.LateSurger]: 1.0, [RunningStyle.LateSurger]: 1.0,
[RunningStyle.EndCloser]: 0.995, [RunningStyle.EndCloser]: 0.995,
[RunningStyle.GreatEscape]: 0.86, [RunningStyle.Runaway]: 0.86,
} as const; } as const;
/** /**
@@ -595,7 +595,7 @@ const accelStrategyPhaseCoeff = {
[RunningStyle.PaceChaser]: [0.985, 1.0, 0.996], [RunningStyle.PaceChaser]: [0.985, 1.0, 0.996],
[RunningStyle.LateSurger]: [0.975, 1.0, 1.0], [RunningStyle.LateSurger]: [0.975, 1.0, 1.0],
[RunningStyle.EndCloser]: [0.945, 1.0, 0.997], [RunningStyle.EndCloser]: [0.945, 1.0, 0.997],
[RunningStyle.GreatEscape]: [1.17, 0.94, 0.956], [RunningStyle.Runaway]: [1.17, 0.94, 0.956],
} as const; } as const;
const surfaceProficiencyMod = [0.1, 0.3, 0.5, 0.7, 0.8, 0.9, 1.0, 1.05] as const; const surfaceProficiencyMod = [0.1, 0.3, 0.5, 0.7, 0.8, 0.9, 1.0, 1.05] as const;
@@ -711,7 +711,7 @@ const conserveStratDistCoef = {
[Distance.Medium]: 0.86, [Distance.Medium]: 0.86,
[Distance.Long]: 0.9, [Distance.Long]: 0.9,
}, },
[RunningStyle.GreatEscape]: { [RunningStyle.Runaway]: {
[Distance.Sprint]: 1, [Distance.Sprint]: 1,
[Distance.Mile]: 1, [Distance.Mile]: 1,
[Distance.Medium]: 1, [Distance.Medium]: 1,
+2 -5
View File
@@ -179,7 +179,7 @@
{ label: 'Style S', y: (x) => downhillAccelEnterChance(x * 1.1) * 100 }, { label: 'Style S', y: (x) => downhillAccelEnterChance(x * 1.1) * 100 },
{ label: 'Style A', y: (x) => downhillAccelEnterChance(x) * 100 }, { label: 'Style A', y: (x) => downhillAccelEnterChance(x) * 100 },
]; ];
const secIsFront = $derived(secSpeedStyle === RunningStyle.FrontRunner || secSpeedStyle === RunningStyle.GreatEscape); const secIsFront = $derived(secSpeedStyle === RunningStyle.FrontRunner || secSpeedStyle === RunningStyle.Runaway);
const secSpeedSeries: Array<ComputedAreas | null> = $derived([ const secSpeedSeries: Array<ComputedAreas | null> = $derived([
{ {
label: 'Early Race', label: 'Early Race',
@@ -326,10 +326,7 @@
<Sec h={3} id="runaway">Runaway</Sec> <Sec h={3} id="runaway">Runaway</Sec>
<p> <p>
The skill <Skill skill={skills.runaway} /> converts front runners into the <i>Great Escape</i> running style. However, no The skill <Skill skill={skills.runaway} /> converts front runners into the Runaway running style.
player has ever uttered the words "Great Escape" when talking about Umamusume, presumably because Runaway is a much cooler
name. ("Great Escape" is a direct translation of Japanese 大逃げ <i>oonige</i>, whereas "Front Runner" is a more liberal
localization of 逃げ <i>nige</i> that technically just means "escape.")
</p> </p>
<p> <p>
Runaways are still front runners for all purposes. The difference is just different numbers for things like base speed and Runaways are still front runners for all purposes. The difference is just different numbers for things like base speed and
+6 -3
View File
@@ -14,7 +14,7 @@
let surfaceApt = $state(race.AptitudeLevel.A); let surfaceApt = $state(race.AptitudeLevel.A);
let distanceApt = $state(race.AptitudeLevel.A); let distanceApt = $state(race.AptitudeLevel.A);
let raceLen = $state(2000); let raceLen = $state(2000);
const styleIsFront = $derived(style === race.RunningStyle.FrontRunner || style === race.RunningStyle.GreatEscape); const styleIsFront = $derived(style === race.RunningStyle.FrontRunner || style === race.RunningStyle.Runaway);
const distanceType = $derived(race.distance(raceLen)); const distanceType = $derived(race.distance(raceLen));
const raceLenType = $derived(race.Distance[distanceType]); const raceLenType = $derived(race.Distance[distanceType]);
@@ -39,7 +39,7 @@
{ label: 'Pace Chaser', y: (x) => race.maxHP(raceLen, race.RunningStyle.PaceChaser, x) }, { label: 'Pace Chaser', y: (x) => race.maxHP(raceLen, race.RunningStyle.PaceChaser, x) },
{ label: 'Late Surger', y: (x) => race.maxHP(raceLen, race.RunningStyle.LateSurger, x) }, { label: 'Late Surger', y: (x) => race.maxHP(raceLen, race.RunningStyle.LateSurger, x) },
{ label: 'End Closer', y: (x) => race.maxHP(raceLen, race.RunningStyle.EndCloser, x) }, { label: 'End Closer', y: (x) => race.maxHP(raceLen, race.RunningStyle.EndCloser, x) },
{ label: 'Runaway', y: (x) => race.maxHP(raceLen, race.RunningStyle.GreatEscape, x) }, { label: 'Runaway', y: (x) => race.maxHP(raceLen, race.RunningStyle.Runaway, x) },
]); ]);
const moveLane: ComputedSeries[] = [{ label: 'Move Lane Modifier', y: (x) => race.moveLaneModifier(x) }]; const moveLane: ComputedSeries[] = [{ label: 'Move Lane Modifier', y: (x) => race.moveLaneModifier(x) }];
const uphill: ComputedSeries[] = [ const uphill: ComputedSeries[] = [
@@ -298,7 +298,10 @@
ref="https://docs.google.com/document/d/15VzW9W2tXBBTibBRbZ8IVpW6HaMX8H0RP03kq6Az7Xg/edit?tab=t.0#heading=h.t9fv1oq5lsu9" ref="https://docs.google.com/document/d/15VzW9W2tXBBTibBRbZ8IVpW6HaMX8H0RP03kq6Az7Xg/edit?tab=t.0#heading=h.t9fv1oq5lsu9"
>Acceleration</Sec >Acceleration</Sec
> >
<p>Acceleration.</p> <p>
Acceleration, i.e. the rate of change of forward velocity when target speed is greater than current speed. Stats do not affect
deceleration (acceleration when target speed is less than current speed).
</p>
{@render statChart(race.Stat.Power, accel, 'Acceleration (m/s²)', [0.1, 0.55], { style: true })} {@render statChart(race.Stat.Power, accel, 'Acceleration (m/s²)', [0.1, 0.55], { style: true })}
<Sec <Sec
+1 -1
View File
@@ -30,7 +30,7 @@
const careerMod = $derived(isCareer ? 400 : 0); const careerMod = $derived(isCareer ? 400 : 0);
const powerStat = $derived(rawPower + careerMod); const powerStat = $derived(rawPower + careerMod);
const gutsStat = $derived(rawGuts + careerMod); const gutsStat = $derived(rawGuts + careerMod);
const style = $derived(isRunaway ? RunningStyle.GreatEscape : RunningStyle.FrontRunner); const style = $derived(isRunaway ? RunningStyle.Runaway : RunningStyle.FrontRunner);
const phases = [Phase.EarlyRace, Phase.MidRace, Phase.LateRace] as const; const phases = [Phase.EarlyRace, Phase.MidRace, Phase.LateRace] as const;
const accel = $derived(phases.map((p) => acceleration(powerStat, style, surfApt, p))); const accel = $derived(phases.map((p) => acceleration(powerStat, style, surfApt, p)));
+48 -50
View File
@@ -1,76 +1,74 @@
<script lang="ts"> <script lang="ts">
import type { ComputedSeries } from '$lib/chart'; import type { ComputedSeries } from '$lib/chart';
import { AptitudeLevel, duelSpeedMod, inverseSpurtSpeed, RunningStyle, spurtSpeed, Stat } from '$lib/race'; import * as race from '$lib/race';
import StatChart from '$lib/StatChart.svelte'; import StatChart from '$lib/StatChart.svelte';
import CalcInfo from '../CalcInfo.svelte'; import CalcInfo from '../CalcInfo.svelte';
const aptsList = Object.entries(AptitudeLevel).filter(([, val]) => typeof val === 'number');
const stylesList = [
['Front Runner', RunningStyle.FrontRunner],
['Pace Chaser', RunningStyle.PaceChaser],
['Late Surger', RunningStyle.LateSurger],
['End Closer', RunningStyle.EndCloser],
['Great Escape', RunningStyle.GreatEscape],
] as const;
const skillSpeeds = [0.45, 0.35, 0.25, 0.15] as const; const skillSpeeds = [0.45, 0.35, 0.25, 0.15] as const;
let rawSpeed: number = $state(1200); let rawSpeed: number = $state(1200);
let rawGuts: number = $state(1200); let rawGuts: number = $state(1200);
let style: RunningStyle = $state(RunningStyle.FrontRunner); let style: race.RunningStyle = $state(race.RunningStyle.FrontRunner);
let opponentStyle: RunningStyle = $state(RunningStyle.PaceChaser); let opponentStyle: race.RunningStyle = $state(race.RunningStyle.PaceChaser);
let distanceApt: AptitudeLevel = $state(AptitudeLevel.S); let distanceApt: race.AptitudeLevel = $state(race.AptitudeLevel.S);
let raceLen: number = $state(2000); let raceLen: number = $state(2000);
let isCareer: boolean = $state(false); let isCareer: boolean = $state(false);
const careerMod = $derived(isCareer ? 400 : 0); const careerMod = $derived(isCareer ? 400 : 0);
const speedStat = $derived(rawSpeed + careerMod); const speedStat = $derived(rawSpeed + careerMod);
const gutsStat = $derived(rawGuts + careerMod); const gutsStat = $derived(rawGuts + careerMod);
const speed = $derived(spurtSpeed(speedStat, gutsStat, style, distanceApt, raceLen)); const speed = $derived(race.spurtSpeed(speedStat, gutsStat, style, distanceApt, raceLen));
const duelBonus = $derived(duelSpeedMod(gutsStat)); const duelBonus = $derived(race.duelSpeedMod(gutsStat));
const sProf = $derived([ const sProf = $derived([
inverseSpurtSpeed(speed, gutsStat, RunningStyle.FrontRunner, AptitudeLevel.S, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.FrontRunner, race.AptitudeLevel.S, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.PaceChaser, AptitudeLevel.S, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.PaceChaser, race.AptitudeLevel.S, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.LateSurger, AptitudeLevel.S, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.LateSurger, race.AptitudeLevel.S, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.EndCloser, AptitudeLevel.S, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.EndCloser, race.AptitudeLevel.S, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.GreatEscape, AptitudeLevel.S, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.Runaway, race.AptitudeLevel.S, raceLen) - careerMod,
]); ]);
const aProf = $derived([ const aProf = $derived([
inverseSpurtSpeed(speed, gutsStat, RunningStyle.FrontRunner, AptitudeLevel.A, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.FrontRunner, race.AptitudeLevel.A, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.PaceChaser, AptitudeLevel.A, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.PaceChaser, race.AptitudeLevel.A, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.LateSurger, AptitudeLevel.A, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.LateSurger, race.AptitudeLevel.A, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.EndCloser, AptitudeLevel.A, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.EndCloser, race.AptitudeLevel.A, raceLen) - careerMod,
inverseSpurtSpeed(speed, gutsStat, RunningStyle.GreatEscape, AptitudeLevel.A, raceLen) - careerMod, race.inverseSpurtSpeed(speed, gutsStat, race.RunningStyle.Runaway, race.AptitudeLevel.A, raceLen) - careerMod,
]); ]);
const skillProf = $derived( const skillProf = $derived(
skillSpeeds.map((v) => [v, inverseSpurtSpeed(speed + v, gutsStat, opponentStyle, AptitudeLevel.S, raceLen) - careerMod]), skillSpeeds.map((v) => [
v,
race.inverseSpurtSpeed(speed + v, gutsStat, opponentStyle, race.AptitudeLevel.S, raceLen) - careerMod,
]),
); );
const speedChart: Array<ComputedSeries | null> = $derived([ const speedChart: Array<ComputedSeries | null> = $derived([
{ label: 'Aptitude S', y: (x) => spurtSpeed(x, gutsStat, style, AptitudeLevel.S, raceLen) }, { label: 'Aptitude S', y: (x) => race.spurtSpeed(x, gutsStat, style, race.AptitudeLevel.S, raceLen) },
{ {
label: `Aptitude ${AptitudeLevel[distanceApt]} + Dueling`, label: `Aptitude ${race.AptitudeLevel[distanceApt]} + Dueling`,
y: (x) => spurtSpeed(x, gutsStat, style, distanceApt, raceLen) + duelBonus, y: (x) => race.spurtSpeed(x, gutsStat, style, distanceApt, raceLen) + duelBonus,
}, },
distanceApt !== AptitudeLevel.S distanceApt !== race.AptitudeLevel.S
? { label: `Aptitude ${AptitudeLevel[distanceApt]}`, y: (x) => spurtSpeed(x, gutsStat, style, distanceApt, raceLen) } ? {
label: `Aptitude ${race.AptitudeLevel[distanceApt]}`,
y: (x) => race.spurtSpeed(x, gutsStat, style, distanceApt, raceLen),
}
: null, : null,
]); ]);
const gutsChart: Array<ComputedSeries | null> = $derived([ const gutsChart: Array<ComputedSeries | null> = $derived([
{ label: 'Aptitude S', y: (x) => spurtSpeed(speedStat, x, style, AptitudeLevel.S, raceLen) }, { label: 'Aptitude S', y: (x) => race.spurtSpeed(speedStat, x, style, race.AptitudeLevel.S, raceLen) },
{ {
label: `Aptitude ${AptitudeLevel[distanceApt]} + Dueling`, label: `Aptitude ${race.AptitudeLevel[distanceApt]} + Dueling`,
y: (x) => spurtSpeed(speedStat, x, style, distanceApt, raceLen) + duelSpeedMod(x), y: (x) => race.spurtSpeed(speedStat, x, style, distanceApt, raceLen) + race.duelSpeedMod(x),
}, },
distanceApt !== AptitudeLevel.S distanceApt !== race.AptitudeLevel.S
? { label: `Aptitude ${AptitudeLevel[distanceApt]}`, y: (x) => spurtSpeed(speedStat, x, style, distanceApt, raceLen) } ? {
label: `Aptitude ${race.AptitudeLevel[distanceApt]}`,
y: (x) => race.spurtSpeed(speedStat, x, style, distanceApt, raceLen),
}
: null, : null,
]); ]);
const range: [number, number] = $derived([ const range: [number, number] = [20, 27.5];
spurtSpeed(200, gutsStat, RunningStyle.GreatEscape, AptitudeLevel.C, raceLen),
spurtSpeed(2000, gutsStat, RunningStyle.EndCloser, AptitudeLevel.S, raceLen) + duelBonus,
]);
</script> </script>
<h1 class="text-4xl">Spurt Speed Calculator</h1> <h1 class="text-4xl">Spurt Speed Calculator</h1>
@@ -86,16 +84,16 @@
<div class="m-4"> <div class="m-4">
<label for="style">Style</label> <label for="style">Style</label>
<select id="style" required bind:value={style} class="w-full"> <select id="style" required bind:value={style} class="w-full">
{#each stylesList as [name, style] (style)} {#each race.RUNNING_STYLES as [name, style] (style)}
<option value={style}>{style === RunningStyle.GreatEscape ? 'Great Escape (Runaway)' : name}</option> <option value={style}>{name}</option>
{/each} {/each}
</select> </select>
</div> </div>
<div class="m-4"> <div class="m-4">
<label for="distanceApt">Distance Aptitude</label> <label for="distanceApt">Distance Aptitude</label>
<select id="distanceApt" required bind:value={distanceApt} class="w-full"> <select id="distanceApt" required bind:value={distanceApt} class="w-full">
{#each aptsList.toReversed() as [name, val] (val)} {#each race.APTITUDE_LEVELS as apt (apt)}
<option value={val}>{name}</option> <option value={apt}>{race.AptitudeLevel[apt]}</option>
{/each} {/each}
</select> </select>
</div> </div>
@@ -112,13 +110,13 @@
<CalcInfo title="Target Spurt Speed" class="flex-1">{speed.toFixed(3)} m/s</CalcInfo> <CalcInfo title="Target Spurt Speed" class="flex-1">{speed.toFixed(3)} m/s</CalcInfo>
<CalcInfo title="Dueling Bonus" class="flex-1">+{duelBonus.toFixed(3)} m/s</CalcInfo> <CalcInfo title="Dueling Bonus" class="flex-1">+{duelBonus.toFixed(3)} m/s</CalcInfo>
</div> </div>
{#each [[AptitudeLevel.A, aProf] as const, [AptitudeLevel.S, sProf] as const] as [level, inv] (level)} {#each [[race.AptitudeLevel.A, aProf] as const, [race.AptitudeLevel.S, sProf] as const] as [level, inv] (level)}
<div class="mx-auto max-w-3xl"> <div class="mx-auto max-w-3xl">
<span class="mt-8 block w-full"> <span class="mt-8 block w-full">
With {AptitudeLevel[level]} proficiency, the equivalent speed is With {race.AptitudeLevel[level]} proficiency, the equivalent speed is
</span> </span>
<div class="flex flex-col md:flex-row"> <div class="flex flex-col md:flex-row">
{#each stylesList as [styleName, s] (s)} {#each race.RUNNING_STYLES as [styleName, s] (s)}
<CalcInfo title={styleName} class={['flex-1', { 'border-2': s === style }]}>{inv[s]}</CalcInfo> <CalcInfo title={styleName} class={['flex-1', { 'border-2': s === style }]}>{inv[s]}</CalcInfo>
{/each} {/each}
</div> </div>
@@ -128,8 +126,8 @@
<span class="mt-8 block w-full"> <span class="mt-8 block w-full">
While a speed skill is active, the equivalent speed for a distance S While a speed skill is active, the equivalent speed for a distance S
<select id="opponentStyle" required bind:value={opponentStyle}> <select id="opponentStyle" required bind:value={opponentStyle}>
{#each stylesList as [name, style] (style)} {#each race.RUNNING_STYLES as [name, style] (style)}
<option value={style}>{style === RunningStyle.GreatEscape ? 'Great Escape (Runaway)' : name}</option> <option value={style}>{style === race.RunningStyle.Runaway ? 'Great Escape (Runaway)' : name}</option>
{/each} {/each}
</select> </select>
is is
@@ -141,6 +139,6 @@
</div> </div>
</div> </div>
<div class="mx-auto grid h-96 grid-cols-1 py-4 md:grid-cols-2"> <div class="mx-auto grid h-96 grid-cols-1 py-4 md:grid-cols-2">
<StatChart stat={Stat.Speed} y={speedChart} yLabel="Spurt Speed (m/s)" xRule={speedStat} {range} /> <StatChart stat={race.Stat.Speed} y={speedChart} yLabel="Spurt Speed (m/s)" xRule={speedStat} {range} />
<StatChart stat={Stat.Guts} y={gutsChart} yLabel="Spurt Speed (m/s)" xRule={gutsStat} {range} /> <StatChart stat={race.Stat.Guts} y={gutsChart} yLabel="Spurt Speed (m/s)" xRule={gutsStat} {range} />
</div> </div>