diff --git a/zenno/src/lib/race.ts b/zenno/src/lib/race.ts index d6b2ba1..d0129c6 100644 --- a/zenno/src/lib/race.ts +++ b/zenno/src/lib/race.ts @@ -1,6 +1,71 @@ // Umamusume race mechanics adapted from KuromiAK's doc: // https://docs.google.com/document/d/15VzW9W2tXBBTibBRbZ8IVpW6HaMX8H0RP03kq6Az7Xg/edit?usp=sharing +import type { Uma } from './data/uma'; + +export interface Runner { + name: string; + + chara_card_id: number; + style: RunningStyle; + mood: Mood; + + speed: number; + stamina: number; + power: number; + guts: number; + wit: number; + + sprint: AptitudeLevel; + mile: AptitudeLevel; + medium: AptitudeLevel; + long: AptitudeLevel; + front: AptitudeLevel; + pace: AptitudeLevel; + late: AptitudeLevel; + end: AptitudeLevel; + turf: AptitudeLevel; + dirt: AptitudeLevel; + + skills: number[]; + unique_level: number; +} + +export function new_runner(name?: string, base_uma?: Uma): Runner { + return { + name: name ?? '', + chara_card_id: base_uma?.chara_card_id ?? 0, + // TODO(zeph): default running style + style: RunningStyle.FrontRunner, + mood: Mood.Normal, + speed: 1200, + stamina: 1200, + power: 1200, + guts: 1200, + wit: 1200, + sprint: base_uma?.sprint ?? AptitudeLevel.A, + mile: base_uma?.mile ?? AptitudeLevel.A, + medium: base_uma?.medium ?? AptitudeLevel.A, + long: base_uma?.long ?? AptitudeLevel.A, + front: base_uma?.front ?? AptitudeLevel.A, + pace: base_uma?.pace ?? AptitudeLevel.A, + late: base_uma?.late ?? AptitudeLevel.A, + end: base_uma?.end ?? AptitudeLevel.A, + turf: base_uma?.turf ?? AptitudeLevel.A, + dirt: base_uma?.dirt ?? AptitudeLevel.A, + skills: base_uma != null ? [base_uma.unique] : [], + unique_level: 4, + }; +} + +export enum Mood { + Awful = -2, + Bad, + Normal, + Good, + Great, +} + export enum RunningStyle { FrontRunner, PaceChaser, @@ -26,6 +91,100 @@ export enum Phase { LateRace, } +namespace Alpha123Umalator { + const aptitude_map = { + G: AptitudeLevel.G, + F: AptitudeLevel.F, + E: AptitudeLevel.E, + D: AptitudeLevel.D, + C: AptitudeLevel.C, + B: AptitudeLevel.B, + A: AptitudeLevel.A, + S: AptitudeLevel.S, + } as const; + type AptitudeString = keyof typeof aptitude_map; + + const style_map = { + Nige: RunningStyle.FrontRunner, + Sentou: RunningStyle.PaceChaser, + Sasi: RunningStyle.LateSurger, + Oikomi: RunningStyle.EndCloser, + Oonige: RunningStyle.GreatEscape, + } as const; + + export interface ImportUma { + outfitId: string; + starCount: number; + speed: number; + stamina: number; + power: number; + guts: number; + wisdom: number; + strategy: keyof typeof style_map; + distanceAptitude: AptitudeString; + surfaceAptitude: AptitudeString; + strategyAptitude: AptitudeString; + aptitudes: [ + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + AptitudeString, + ]; + skills: string[]; + uniqueLv: number; + mood: Mood; + popularity: number; + } + + export function load(obj: ImportUma, name?: string): Runner { + return { + name: name ?? '', + chara_card_id: obj.outfitId !== '' ? parseInt(obj.outfitId) : 0, + style: style_map[obj.strategy], + mood: obj.mood, + speed: obj.speed, + stamina: obj.stamina, + power: obj.power, + guts: obj.guts, + wit: obj.wisdom, + sprint: aptitude_map[obj.aptitudes[0]], + mile: aptitude_map[obj.aptitudes[1]], + medium: aptitude_map[obj.aptitudes[2]], + long: aptitude_map[obj.aptitudes[3]], + front: aptitude_map[obj.aptitudes[4]], + pace: aptitude_map[obj.aptitudes[5]], + late: aptitude_map[obj.aptitudes[6]], + end: aptitude_map[obj.aptitudes[7]], + turf: aptitude_map[obj.aptitudes[8]], + dirt: aptitude_map[obj.aptitudes[9]], + skills: obj.skills.map((s) => parseInt(s)), + unique_level: obj.uniqueLv, + }; + } +} + +export function import_runner(obj: any, name?: string): Runner | null { + // TODO(zeph): check for keys that identify the uma source + if (typeof obj === 'object') { + try { + const r = Alpha123Umalator.load(obj as Alpha123Umalator.ImportUma, name); + // TODO(zeph): validate? + return r; + } catch (exc) { + console.warn('failed to import', obj, 'as alpha123 umalator:', exc); + return null; + } + } + console.warn('no guess on how to import', obj); + return null; +} + function baseSpeed(raceLen: number): number { return 20 - (raceLen - 2000) / 1000; }