结构(旧 game/core+engine → 新 engine/ 域): - engine/kernel/ 时钟/随机/插件协议/fxqueue/timesense/format/urgency/guide/names(原 core) - engine/narrative/ legacy/报告/列传/谱系/年轴(原 core 叙事族) - engine/runtime/ World/creation/pcgen/ApiFacade/capabilities/pluginManager/boot/clocks + Systems/*(12 系统) - engine/sim/ Market(未来 WorldSim 同行) - 旧 game/core、engine/systems、engine/world.ts 等路径全部废弃(无 re-export 兼容层) 验证:35 套件/967 测试全绿(金钟罩三档零漂移=纯搬迁无行为变化) typecheck 0 error
204 lines
5.5 KiB
TypeScript
204 lines
5.5 KiB
TypeScript
import { Character, GameState, NpcFamilyState, RealmMajor } from '../../types/domain'
|
|
import { Rng, seedToRng } from '../kernel/rng'
|
|
import { randomSurname, MALE_GIVEN, FEMALE_GIVEN } from '../kernel/names'
|
|
import { newCharacter } from './pcgen'
|
|
import { NPCS } from '../../data/npcs'
|
|
import { World } from './World'
|
|
|
|
export interface NewGameOptions {
|
|
seed: string
|
|
surname: string
|
|
familyName: string
|
|
motto: string
|
|
difficulty: 'easy' | 'normal' | 'hard'
|
|
}
|
|
|
|
export function createWorldState(opts: NewGameOptions): GameState {
|
|
const rng = new Rng(seedToRng(opts.seed))
|
|
const surname = opts.surname.trim() || randomSurname(rng)
|
|
const familyName = opts.familyName.trim() || `${surname}家`
|
|
const diff = opts.difficulty
|
|
const stones = diff === 'easy' ? 1200 : diff === 'normal' ? 800 : 550
|
|
const npcStrength = diff === 'easy' ? 0.9 : diff === 'normal' ? 1 : 1.15
|
|
|
|
const state: GameState = {
|
|
schemaVersion: 1,
|
|
seed: opts.seed,
|
|
rng: rng.getState(),
|
|
year: 1,
|
|
month: 1,
|
|
seq: 0,
|
|
family: {
|
|
surname,
|
|
name: familyName,
|
|
motto: opts.motto.trim() || '耕读传家,术法继世',
|
|
crest: '#c9a227',
|
|
estate: '青云庄',
|
|
yearFounded: 1,
|
|
generation: 1,
|
|
reputation: 5,
|
|
stones,
|
|
inventory: {
|
|
lingcao: 60,
|
|
lingkuang: 30,
|
|
beastcore: 0,
|
|
'pill-qiyuan': 2,
|
|
'pill-ningyuan': 1
|
|
},
|
|
buildings: { lingtian: 1, zongci: 1 },
|
|
techniques: ['t-qinglian', 't-houtu'],
|
|
missionIds: [],
|
|
headId: '',
|
|
difficulty: diff,
|
|
flag: { priceMult: 1, tenants: 0, headBless: 0 }
|
|
},
|
|
members: {},
|
|
npcFamilies: Object.fromEntries(
|
|
NPCS.map((n) => [
|
|
n.id,
|
|
{
|
|
id: n.id,
|
|
name: n.name,
|
|
region: n.region,
|
|
power: Math.round(n.initialPower * npcStrength),
|
|
relation: 0,
|
|
allied: false,
|
|
raidCount: 0
|
|
} as NpcFamilyState
|
|
])
|
|
),
|
|
missions: [],
|
|
chronicle: [],
|
|
battles: [],
|
|
eventQueue: [],
|
|
completedEvents: [],
|
|
flags: {},
|
|
totalTicks: 0,
|
|
finance: { accum: 0 },
|
|
yearStats: { births: 0, deaths: 0 },
|
|
yearlyReports: [],
|
|
stats: {
|
|
repPeak: 5,
|
|
popPeak: 5,
|
|
maxRealmIdx: 25,
|
|
techniqueGrand: 0,
|
|
tourneyHistory: [],
|
|
feishengCount: 0
|
|
}
|
|
}
|
|
|
|
const w = new World(state, [])
|
|
const male1: string = rng.pick(MALE_GIVEN)
|
|
const female1: string = rng.pick(FEMALE_GIVEN)
|
|
|
|
const head: Character = newCharacter(rng, {
|
|
name: `${surname}${male1}`,
|
|
gender: 'male',
|
|
generation: 1,
|
|
bornYear: 1 - 35,
|
|
age: 35,
|
|
realm: { major: 'qi', minor: 4 },
|
|
isHead: true,
|
|
isFounder: true,
|
|
fortuneBase: 7
|
|
})
|
|
head.realmProgress = 40
|
|
head.techniqueId = 't-qinglian'
|
|
head.traits = ['tiangan', 'shensui']
|
|
|
|
const wife: Character = newCharacter(rng, {
|
|
name: `${surname}${female1}`,
|
|
gender: 'female',
|
|
generation: 1,
|
|
bornYear: 1 - 33,
|
|
age: 33,
|
|
realm: { major: 'qi', minor: 2 },
|
|
fortuneBase: 6
|
|
})
|
|
wife.realmProgress = 55
|
|
head.spouseId = 'x2'
|
|
wife.spouseId = 'x1'
|
|
head.children = ['x3', 'x5']
|
|
|
|
const elderBrother: Character = newCharacter(rng, {
|
|
name: `${surname}${rng.pick(MALE_GIVEN)}`,
|
|
gender: 'male',
|
|
generation: 2,
|
|
bornYear: 1 - 16,
|
|
age: 16,
|
|
realm: { major: 'qi', minor: 1 },
|
|
father: head,
|
|
mother: wife
|
|
})
|
|
elderBrother.realmProgress = 20
|
|
elderBrother.techniqueId = 't-houtu'
|
|
elderBrother.fatherId = 'x1'
|
|
elderBrother.motherId = 'x2'
|
|
|
|
const sister: Character = newCharacter(rng, {
|
|
name: `${surname}${rng.pick(FEMALE_GIVEN)}`,
|
|
gender: 'female',
|
|
generation: 2,
|
|
bornYear: 1 - 12,
|
|
age: 12,
|
|
realm: { major: 'mortal', minor: 0 },
|
|
father: head,
|
|
mother: wife
|
|
})
|
|
sister.fatherId = 'x1'
|
|
sister.motherId = 'x2'
|
|
|
|
const uncle: Character = newCharacter(rng, {
|
|
name: `${surname}${rng.pick(MALE_GIVEN)}`,
|
|
gender: 'male',
|
|
generation: 1,
|
|
bornYear: 1 - 45,
|
|
age: 45,
|
|
realm: { major: 'qi', minor: 6 },
|
|
fortuneBase: 6
|
|
})
|
|
uncle.realmProgress = 30
|
|
uncle.techniqueId = 't-houtu'
|
|
uncle.traits = ['xinheng', 'shensui']
|
|
uncle.id = 'x4'
|
|
uncle.spouseHouse = '四海王氏'
|
|
uncle.children = []
|
|
|
|
head.id = 'x1'
|
|
wife.id = 'x2'
|
|
elderBrother.id = 'x3'
|
|
sister.id = 'x5'
|
|
wife.children = ['x3', 'x5']
|
|
|
|
state.members = { x1: head, x2: wife, x3: elderBrother, x4: uncle, x5: sister }
|
|
state.family.headId = 'x1'
|
|
state.seq = 10
|
|
|
|
w.chronicle('misc', `${surname}氏一族定居山阴,立${familyName}。庄主${head.name},年方三十五。`, head.id, true)
|
|
w.log('info', `青云庄立,${familyName}始兴。`)
|
|
return state
|
|
}
|
|
|
|
export function findInheritor(world: World): Character | undefined {
|
|
const alive = world.aliveMembers()
|
|
if (alive.length === 0) return undefined
|
|
const head = world.state.members[world.state.family.headId]
|
|
const candidates = alive.filter((c) => c.id !== head?.id)
|
|
if (candidates.length === 0) return undefined
|
|
const byBlood = candidates
|
|
.filter((c) => (head && head.children.includes(c.id)) || (c.fatherId === head?.id))
|
|
.sort((a, b) => world.ageOf(b) - world.ageOf(a))
|
|
if (byBlood.length > 0) return byBlood[0]
|
|
const byRealm = [...candidates].sort((a, b) => {
|
|
const ra = realmRank(a.realm)
|
|
const rb = realmRank(b.realm)
|
|
return rb - ra || b.charm - a.charm || world.ageOf(b) - world.ageOf(a)
|
|
})
|
|
return byRealm[0]
|
|
}
|
|
|
|
function realmRank(realm: { major: RealmMajor; minor: number }): number {
|
|
const order: RealmMajor[] = ['mortal', 'qi', 'foundation', 'core', 'nascent', 'spirit']
|
|
return order.indexOf(realm.major) * 10 + realm.minor
|
|
}
|