diff --git a/packages/core/src/game.ts b/packages/core/src/game.ts index 71d5fa8..166ed92 100644 --- a/packages/core/src/game.ts +++ b/packages/core/src/game.ts @@ -19,13 +19,17 @@ export { pull } from '@/talent' import { replacement, additionalPoints } from '@/talent' import type { ReplacementResult, AdditionalPoints } from '@/talent' +import type { RNG } from '@remake/vitex' export interface TalentsPickedResult { talents: ReplacementResult additionalPoints: AdditionalPoints } -export function talentsPicked(talents: Iterable) { - const r = replacement(talents) +export function talentsPicked( + talents: Iterable, + rng?: RNG, +): TalentsPickedResult { + const r = replacement(talents, rng) const ap = additionalPoints(r.talents) return { talents: r, additionalPoints: ap } } @@ -63,16 +67,20 @@ export interface NextResult { end: boolean } -export function next(state: GameState, profile: ProfileState): NextResult { +export function next( + state: GameState, + profile: ProfileState, + rng?: RNG, +): NextResult { let s = produce(state, draft => { draft.props = propsEffect(state.props, { age: 1 }) }) const age = s.props.current.age - const tr = talentTrigger(s, profile) + const tr = talentTrigger(s, profile, rng) const events = ages .get(age)! .event.filter(([e]) => eventCheck(e, tr.state, profile)) - const event = pickWeight(events)! + const event = pickWeight(events, rng)! const er = eventTrigger(event, tr.state, profile) const ar = achievementTrigger('TRAJECTORY', er.state, profile) const end = ar.state.life < 1 diff --git a/packages/core/src/talent.ts b/packages/core/src/talent.ts index d3dd8a4..5594bc6 100644 --- a/packages/core/src/talent.ts +++ b/packages/core/src/talent.ts @@ -4,7 +4,7 @@ import type { Properties } from '@/state' import type { GameState, ProfileState } from '@/state' import { propsEffect, createFlatState } from './state' import { check } from '@remake/condition' -import { pick, pickWeight } from '@remake/vitex' +import { pick, pickWeight, type RNG } from '@remake/vitex' import { produce } from 'immer' import type { TriggerResult } from '@/game' @@ -64,7 +64,7 @@ export interface PullOptions { rate: RateOptions } -export function pull(options: PullOptions, profile: ProfileState) { +export function pull(options: PullOptions, profile: ProfileState, rng?: RNG) { const rate = Array.from( talentRateWithAddition(options.rate, profile).entries(), ) @@ -72,10 +72,10 @@ export function pull(options: PullOptions, profile: ProfileState) { if (profile.lockedTalent) result.push(profile.lockedTalent) const map = new Map(Grades.map(g => [g, new Set(GradeMap.get(g))])) for (let i = options.count - result.length; i > 0; i--) { - const grade = pickWeight(rate)! ?? 0 + const grade = pickWeight(rate, rng)! ?? 0 const set = map.get(grade)! if (set.size === 0) continue - const id = pick(Array.from(set))! + const id = pick(Array.from(set), rng)! result.push(id) set.delete(id) } @@ -100,23 +100,23 @@ export function exclude(talent: Talent['id'], list: Iterable) { return null } -function chainReplace(t: Talent['id'], ts: Set) { +function chainReplace(t: Talent['id'], ts: Set, rng?: RNG) { const { replacement: r } = talents.get(t)! if (!r) return null let picked: Talent['id'] | null = null if (r.talent) { const filtered = r.talent.filter(([id]) => exclude(id, ts) == null) - picked = pickWeight(filtered) + picked = pickWeight(filtered, rng) } else if (r.grade) { const filtered = GradeMap.get(r.grade)!.filter( id => exclude(id, ts) == null, ) - picked = pick(filtered) + picked = pick(filtered, rng) } if (!picked) return null const nts = new Set(ts) nts.add(picked) - const next = chainReplace(picked, nts) as Talent['id'][] | null + const next = chainReplace(picked, nts, rng) as Talent['id'][] | null if (next) return [picked, ...next] return [picked] } @@ -126,11 +126,14 @@ export interface ReplacementResult { chains: Map } -export function replacement(list: Iterable): ReplacementResult { +export function replacement( + list: Iterable, + rng?: RNG, +): ReplacementResult { const set = new Set(list) const chains = new Map() as ReplacementResult['chains'] for (const talent of list) { - const chain = chainReplace(talent, set) + const chain = chainReplace(talent, set, rng) if (!chain) continue chains.set(talent, chain) chain.forEach(t => set.add(t)) @@ -173,6 +176,7 @@ const EffectRandomProperties = [ export function trigger( state: GameState, profile: ProfileState, + rng?: RNG, ): TriggerResult { const flatState = createFlatState(state, profile) const triggers: Talent['id'][] = [] @@ -196,7 +200,7 @@ export function trigger( if (effect.MNY) pe.money = effect.MNY if (effect.SPR) pe.spirit = effect.SPR if (effect.RND) { - const key = pick(EffectRandomProperties)! + const key = pick(EffectRandomProperties, rng)! pe[key] = (pe[key] ?? 0) || effect.RND } draft.props = propsEffect(draft.props, pe)