v0.1.17: 天下为市——世界真炉膛(市场实体化+NPC博弈+灾年持续)

【A 市场实体化(真库存循环)】
- 世界呼吸:池月供给 × 潮汐span - 常驻需求(worldSupplyRate 2% vs worldDemandRate 1.5%)
- NPC 上桌:def.sells/buys 逐月入池出池——池浅采不到→power-15%,池深抛货→市场暖意
- 玩家交易回写:buy 浅池价涨/sell 盈池价跌(tradeSettle 0.35 份额粒度);池深<35% 断供拒单(12% 是枯井)
- marketPrice 统一走 marketMultFor;本地 POOL_BASE/TECH 复刻清除(worldsim-data 单源)

【B 世界格局博弈】
- 战争伤骨:劫掠胜负回写 power(败-18%/胜+6%)+ dead 字段 raidCount/warCooldownYear 启用
- 社交回响:赠礼回礼(30% 灵石/30% 灵草)+ power 微涨;联姻/和约/结盟皆涨 power
- NPC 关系网:relationsWithOthers 填实(同风格亲30~55/异风格隙-35~15)+ 年首±5 漂移;世仇<-50 年首互攻(败方-18%)
- 灾年共苦:灾年 NPC 贸易 ×0.7;tide 对供给 ±0.3 弹性
- 灾年持续 6 月渐退;灾起/灾散快讯(kind 标记)

【UI】
- 天下面板:池深百分比(含断供阈值 tooltip)/本族天下排位/灾年余月
- 快讯响应化:行情见顶抛售5/见底吃进5/灾年救济(50灵石→关系8)
- MarketPanel 法帖价格改 techniquePrice()(硬编码清除)

【测试】994 全绿(38 套件,新增世界炉膛 8 例);金钟罩 0.1.17 基线固化
This commit is contained in:
2026-08-23 14:24:23 +08:00
parent 809707408b
commit ea9f5c9c5d
17 changed files with 353 additions and 53 deletions
+8 -10
View File
@@ -11,14 +11,8 @@ export function marketPrice(w: World, itemId: string): number {
const fam = w.state.family
const mult = typeof fam.flag['priceMult'] === 'number' ? (fam.flag['priceMult'] as number) : 1
const mood = fam.reputation >= 40 ? 1.06 : fam.reputation >= 20 ? 1.02 : 0.98
// 世界行情乘子(缺省 1
let simMult = 1
if (w.state.worldSim?.marketPool) {
const pool = w.state.worldSim.marketPool[itemId] as number | undefined
const basePool = POOL_BASE[itemId] ?? 100
const r = (pool ?? basePool) / basePool
simMult = Math.max(0.55, Math.min(2.3, r))
}
// 世界行情乘子(唯一读口:worldSim.marketMultFor;无 sim 时 1
const simMult = w.state.worldSim ? new WorldSim(w).marketMultFor(itemId) : 1
// 利己(priceMult)与信誉修正
const sellers = w.aliveMembers().filter((c) => traitBonuses(c).priceMult > 0).length
const liarPct = Math.min(0.2, sellers * 0.04)
@@ -28,10 +22,14 @@ export function marketPrice(w: World, itemId: string): number {
export function buyItem(w: World, itemId: string, count: number): boolean {
const fam = w.state.family
if (!pack().items[itemId]) return false
const sim = w.state.worldSim ? new WorldSim(w) : null
// 断供告急:池深低于下限时拒单(零库存市场无货可买;世界生产与 NPC 供给会回填)
if (sim && sim.poolDepthOf(itemId) < WORLDSIM.tradeFloorPct && w.state.totalTicks > 12) return false
const total = marketPrice(w, itemId) * count
if (total > fam.stones) return false
fam.stones -= total
fam.inventory[itemId] = (fam.inventory[itemId] ?? 0) + count
sim?.tradeSettle(itemId, -count)
return true
}
@@ -42,6 +40,7 @@ export function sellItem(w: World, itemId: string, count: number): boolean {
if (have < count) return false
fam.inventory[itemId] = have - count
fam.stones += marketPrice(w, itemId) * count
if (w.state.worldSim) new WorldSim(w).tradeSettle(itemId, count)
return true
}
@@ -59,8 +58,7 @@ export function techniquePrice(techId: string): number {
}
import { TECHNIQUES } from '../../data/techniques'
const POOL_BASE: Record<string, number> = { lingcao: 600, lingkuang: 300, beastcore: 80, 'pill-qiyuan': 90, 'pill-ningyuan': 40 }
import { WORLDSIM } from './worldsim-data'
const TECHNIQUE_GRADE_PRICE: Record<number, number> = { 1: 120, 2: 300, 3: 700, 4: 1600 }
const TECH_GRADE_BASE: Record<string, number> = Object.fromEntries(