@its-not-rocket-science/ananke 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +135 -0
- package/LICENSE +21 -0
- package/README.md +2199 -0
- package/STABLE_API.md +266 -0
- package/dist/src/anatomy/anatomy-compiler.d.ts +14 -0
- package/dist/src/anatomy/anatomy-compiler.js +277 -0
- package/dist/src/anatomy/anatomy-contracts.d.ts +94 -0
- package/dist/src/anatomy/anatomy-contracts.js +1 -0
- package/dist/src/anatomy/anatomy-helpers.d.ts +82 -0
- package/dist/src/anatomy/anatomy-helpers.js +233 -0
- package/dist/src/anatomy/anatomy-schema.d.ts +28 -0
- package/dist/src/anatomy/anatomy-schema.js +388 -0
- package/dist/src/anatomy/index.d.ts +4 -0
- package/dist/src/anatomy/index.js +4 -0
- package/dist/src/archetypes.d.ts +87 -0
- package/dist/src/archetypes.js +285 -0
- package/dist/src/arena.d.ts +173 -0
- package/dist/src/arena.js +695 -0
- package/dist/src/bridge/bridge-engine.d.ts +46 -0
- package/dist/src/bridge/bridge-engine.js +252 -0
- package/dist/src/bridge/index.d.ts +4 -0
- package/dist/src/bridge/index.js +5 -0
- package/dist/src/bridge/interpolation.d.ts +64 -0
- package/dist/src/bridge/interpolation.js +130 -0
- package/dist/src/bridge/mapping.d.ts +33 -0
- package/dist/src/bridge/mapping.js +54 -0
- package/dist/src/bridge/types.d.ts +94 -0
- package/dist/src/bridge/types.js +2 -0
- package/dist/src/campaign.d.ts +141 -0
- package/dist/src/campaign.js +235 -0
- package/dist/src/channels.d.ts +15 -0
- package/dist/src/channels.js +20 -0
- package/dist/src/chronicle.d.ts +124 -0
- package/dist/src/chronicle.js +232 -0
- package/dist/src/collective-activities.d.ts +154 -0
- package/dist/src/collective-activities.js +247 -0
- package/dist/src/competence/acoustic.d.ts +101 -0
- package/dist/src/competence/acoustic.js +242 -0
- package/dist/src/competence/catalogue.d.ts +30 -0
- package/dist/src/competence/catalogue.js +241 -0
- package/dist/src/competence/crafting.d.ts +35 -0
- package/dist/src/competence/crafting.js +88 -0
- package/dist/src/competence/engineering.d.ts +53 -0
- package/dist/src/competence/engineering.js +108 -0
- package/dist/src/competence/framework.d.ts +68 -0
- package/dist/src/competence/framework.js +694 -0
- package/dist/src/competence/index.d.ts +12 -0
- package/dist/src/competence/index.js +13 -0
- package/dist/src/competence/interspecies.d.ts +81 -0
- package/dist/src/competence/interspecies.js +108 -0
- package/dist/src/competence/language.d.ts +79 -0
- package/dist/src/competence/language.js +115 -0
- package/dist/src/competence/naturalist.d.ts +97 -0
- package/dist/src/competence/naturalist.js +187 -0
- package/dist/src/competence/navigation.d.ts +24 -0
- package/dist/src/competence/navigation.js +48 -0
- package/dist/src/competence/performance.d.ts +125 -0
- package/dist/src/competence/performance.js +210 -0
- package/dist/src/competence/teaching.d.ts +64 -0
- package/dist/src/competence/teaching.js +121 -0
- package/dist/src/competence/willpower.d.ts +74 -0
- package/dist/src/competence/willpower.js +114 -0
- package/dist/src/crafting/index.d.ts +55 -0
- package/dist/src/crafting/index.js +229 -0
- package/dist/src/crafting/manufacturing.d.ts +83 -0
- package/dist/src/crafting/manufacturing.js +165 -0
- package/dist/src/crafting/materials.d.ts +53 -0
- package/dist/src/crafting/materials.js +120 -0
- package/dist/src/crafting/recipes.d.ts +75 -0
- package/dist/src/crafting/recipes.js +233 -0
- package/dist/src/crafting/workshops.d.ts +61 -0
- package/dist/src/crafting/workshops.js +170 -0
- package/dist/src/debug.d.ts +86 -0
- package/dist/src/debug.js +76 -0
- package/dist/src/derive.d.ts +21 -0
- package/dist/src/derive.js +88 -0
- package/dist/src/describe.d.ts +29 -0
- package/dist/src/describe.js +276 -0
- package/dist/src/dialogue.d.ts +122 -0
- package/dist/src/dialogue.js +266 -0
- package/dist/src/dist.d.ts +20 -0
- package/dist/src/dist.js +39 -0
- package/dist/src/downtime.d.ts +89 -0
- package/dist/src/downtime.js +391 -0
- package/dist/src/economy.d.ts +116 -0
- package/dist/src/economy.js +182 -0
- package/dist/src/emotional-contagion.d.ts +142 -0
- package/dist/src/emotional-contagion.js +274 -0
- package/dist/src/equipment.d.ts +206 -0
- package/dist/src/equipment.js +598 -0
- package/dist/src/faction.d.ts +102 -0
- package/dist/src/faction.js +237 -0
- package/dist/src/generate.d.ts +35 -0
- package/dist/src/generate.js +166 -0
- package/dist/src/index.d.ts +42 -0
- package/dist/src/index.js +54 -0
- package/dist/src/inheritance.d.ts +69 -0
- package/dist/src/inheritance.js +136 -0
- package/dist/src/inventory.d.ts +194 -0
- package/dist/src/inventory.js +637 -0
- package/dist/src/item-durability.d.ts +69 -0
- package/dist/src/item-durability.js +308 -0
- package/dist/src/legend.d.ts +97 -0
- package/dist/src/legend.js +269 -0
- package/dist/src/lod.d.ts +9 -0
- package/dist/src/lod.js +84 -0
- package/dist/src/metrics.d.ts +51 -0
- package/dist/src/metrics.js +91 -0
- package/dist/src/model3d.d.ts +138 -0
- package/dist/src/model3d.js +214 -0
- package/dist/src/mythology.d.ts +101 -0
- package/dist/src/mythology.js +308 -0
- package/dist/src/narrative-render.d.ts +42 -0
- package/dist/src/narrative-render.js +194 -0
- package/dist/src/narrative-stress.d.ts +123 -0
- package/dist/src/narrative-stress.js +183 -0
- package/dist/src/narrative.d.ts +44 -0
- package/dist/src/narrative.js +257 -0
- package/dist/src/party.d.ts +70 -0
- package/dist/src/party.js +226 -0
- package/dist/src/polity.d.ts +262 -0
- package/dist/src/polity.js +398 -0
- package/dist/src/presets.d.ts +42 -0
- package/dist/src/presets.js +170 -0
- package/dist/src/progression.d.ts +170 -0
- package/dist/src/progression.js +256 -0
- package/dist/src/quest-generators.d.ts +76 -0
- package/dist/src/quest-generators.js +534 -0
- package/dist/src/quest.d.ts +239 -0
- package/dist/src/quest.js +520 -0
- package/dist/src/relationships-effects.d.ts +75 -0
- package/dist/src/relationships-effects.js +219 -0
- package/dist/src/relationships.d.ts +104 -0
- package/dist/src/relationships.js +347 -0
- package/dist/src/replay.d.ts +47 -0
- package/dist/src/replay.js +82 -0
- package/dist/src/rng.d.ts +9 -0
- package/dist/src/rng.js +37 -0
- package/dist/src/settlement-services.d.ts +67 -0
- package/dist/src/settlement-services.js +267 -0
- package/dist/src/settlement.d.ts +143 -0
- package/dist/src/settlement.js +419 -0
- package/dist/src/sim/action.d.ts +28 -0
- package/dist/src/sim/action.js +12 -0
- package/dist/src/sim/aging.d.ts +95 -0
- package/dist/src/sim/aging.js +243 -0
- package/dist/src/sim/ai/decide.d.ts +10 -0
- package/dist/src/sim/ai/decide.js +267 -0
- package/dist/src/sim/ai/perception.d.ts +12 -0
- package/dist/src/sim/ai/perception.js +54 -0
- package/dist/src/sim/ai/personality.d.ts +54 -0
- package/dist/src/sim/ai/personality.js +202 -0
- package/dist/src/sim/ai/presets.d.ts +2 -0
- package/dist/src/sim/ai/presets.js +28 -0
- package/dist/src/sim/ai/system.d.ts +6 -0
- package/dist/src/sim/ai/system.js +13 -0
- package/dist/src/sim/ai/targeting.d.ts +8 -0
- package/dist/src/sim/ai/targeting.js +42 -0
- package/dist/src/sim/ai/types.d.ts +14 -0
- package/dist/src/sim/ai/types.js +1 -0
- package/dist/src/sim/body.d.ts +9 -0
- package/dist/src/sim/body.js +32 -0
- package/dist/src/sim/bodyplan.d.ts +161 -0
- package/dist/src/sim/bodyplan.js +677 -0
- package/dist/src/sim/capability.d.ts +135 -0
- package/dist/src/sim/capability.js +8 -0
- package/dist/src/sim/combat.d.ts +21 -0
- package/dist/src/sim/combat.js +77 -0
- package/dist/src/sim/commandBuilders.d.ts +11 -0
- package/dist/src/sim/commandBuilders.js +39 -0
- package/dist/src/sim/commands.d.ts +71 -0
- package/dist/src/sim/commands.js +8 -0
- package/dist/src/sim/condition.d.ts +35 -0
- package/dist/src/sim/condition.js +21 -0
- package/dist/src/sim/cone.d.ts +40 -0
- package/dist/src/sim/cone.js +44 -0
- package/dist/src/sim/context.d.ts +68 -0
- package/dist/src/sim/context.js +1 -0
- package/dist/src/sim/density.d.ts +14 -0
- package/dist/src/sim/density.js +33 -0
- package/dist/src/sim/disease.d.ts +141 -0
- package/dist/src/sim/disease.js +353 -0
- package/dist/src/sim/entity.d.ts +251 -0
- package/dist/src/sim/entity.js +19 -0
- package/dist/src/sim/events.d.ts +25 -0
- package/dist/src/sim/events.js +5 -0
- package/dist/src/sim/explosion.d.ts +40 -0
- package/dist/src/sim/explosion.js +40 -0
- package/dist/src/sim/formation-unit.d.ts +138 -0
- package/dist/src/sim/formation-unit.js +197 -0
- package/dist/src/sim/formation.d.ts +12 -0
- package/dist/src/sim/formation.js +54 -0
- package/dist/src/sim/frontage.d.ts +30 -0
- package/dist/src/sim/frontage.js +84 -0
- package/dist/src/sim/grapple.d.ts +100 -0
- package/dist/src/sim/grapple.js +480 -0
- package/dist/src/sim/hazard.d.ts +104 -0
- package/dist/src/sim/hazard.js +201 -0
- package/dist/src/sim/hydrostatic.d.ts +58 -0
- package/dist/src/sim/hydrostatic.js +117 -0
- package/dist/src/sim/impairment.d.ts +20 -0
- package/dist/src/sim/impairment.js +162 -0
- package/dist/src/sim/indexing.d.ts +7 -0
- package/dist/src/sim/indexing.js +7 -0
- package/dist/src/sim/injury.d.ts +54 -0
- package/dist/src/sim/injury.js +66 -0
- package/dist/src/sim/intent.d.ts +26 -0
- package/dist/src/sim/intent.js +7 -0
- package/dist/src/sim/kernel.d.ts +45 -0
- package/dist/src/sim/kernel.js +1992 -0
- package/dist/src/sim/kinds.d.ts +64 -0
- package/dist/src/sim/kinds.js +56 -0
- package/dist/src/sim/knockback.d.ts +50 -0
- package/dist/src/sim/knockback.js +82 -0
- package/dist/src/sim/limb.d.ts +48 -0
- package/dist/src/sim/limb.js +78 -0
- package/dist/src/sim/medical.d.ts +32 -0
- package/dist/src/sim/medical.js +33 -0
- package/dist/src/sim/morale.d.ts +69 -0
- package/dist/src/sim/morale.js +92 -0
- package/dist/src/sim/mount.d.ts +150 -0
- package/dist/src/sim/mount.js +225 -0
- package/dist/src/sim/nutrition.d.ts +74 -0
- package/dist/src/sim/nutrition.js +168 -0
- package/dist/src/sim/occlusion.d.ts +8 -0
- package/dist/src/sim/occlusion.js +71 -0
- package/dist/src/sim/push.d.ts +11 -0
- package/dist/src/sim/push.js +79 -0
- package/dist/src/sim/ranged.d.ts +44 -0
- package/dist/src/sim/ranged.js +69 -0
- package/dist/src/sim/seeds.d.ts +3 -0
- package/dist/src/sim/seeds.js +16 -0
- package/dist/src/sim/sensory-extended.d.ts +103 -0
- package/dist/src/sim/sensory-extended.js +181 -0
- package/dist/src/sim/sensory.d.ts +38 -0
- package/dist/src/sim/sensory.js +109 -0
- package/dist/src/sim/skills.d.ts +70 -0
- package/dist/src/sim/skills.js +69 -0
- package/dist/src/sim/sleep.d.ts +107 -0
- package/dist/src/sim/sleep.js +215 -0
- package/dist/src/sim/spatial.d.ts +8 -0
- package/dist/src/sim/spatial.js +59 -0
- package/dist/src/sim/step/capability.d.ts +8 -0
- package/dist/src/sim/step/capability.js +77 -0
- package/dist/src/sim/step/concentration.d.ts +9 -0
- package/dist/src/sim/step/concentration.js +25 -0
- package/dist/src/sim/step/effects.d.ts +17 -0
- package/dist/src/sim/step/effects.js +96 -0
- package/dist/src/sim/step/energy.d.ts +3 -0
- package/dist/src/sim/step/energy.js +31 -0
- package/dist/src/sim/step/hazards.d.ts +4 -0
- package/dist/src/sim/step/hazards.js +19 -0
- package/dist/src/sim/step/injury.d.ts +10 -0
- package/dist/src/sim/step/injury.js +353 -0
- package/dist/src/sim/step/morale.d.ts +11 -0
- package/dist/src/sim/step/morale.js +130 -0
- package/dist/src/sim/step/movement.d.ts +5 -0
- package/dist/src/sim/step/movement.js +172 -0
- package/dist/src/sim/step/push.d.ts +11 -0
- package/dist/src/sim/step/push.js +79 -0
- package/dist/src/sim/step/substances.d.ts +3 -0
- package/dist/src/sim/step/substances.js +75 -0
- package/dist/src/sim/substance.d.ts +38 -0
- package/dist/src/sim/substance.js +57 -0
- package/dist/src/sim/systemic-toxicology.d.ts +109 -0
- package/dist/src/sim/systemic-toxicology.js +263 -0
- package/dist/src/sim/team.d.ts +9 -0
- package/dist/src/sim/team.js +37 -0
- package/dist/src/sim/tech.d.ts +36 -0
- package/dist/src/sim/tech.js +46 -0
- package/dist/src/sim/terrain.d.ts +121 -0
- package/dist/src/sim/terrain.js +141 -0
- package/dist/src/sim/testing.d.ts +13 -0
- package/dist/src/sim/testing.js +100 -0
- package/dist/src/sim/thermoregulation.d.ts +77 -0
- package/dist/src/sim/thermoregulation.js +161 -0
- package/dist/src/sim/tick.d.ts +3 -0
- package/dist/src/sim/tick.js +3 -0
- package/dist/src/sim/toxicology.d.ts +52 -0
- package/dist/src/sim/toxicology.js +104 -0
- package/dist/src/sim/trace.d.ts +141 -0
- package/dist/src/sim/trace.js +1 -0
- package/dist/src/sim/tuning.d.ts +16 -0
- package/dist/src/sim/tuning.js +42 -0
- package/dist/src/sim/vec3.d.ts +14 -0
- package/dist/src/sim/vec3.js +31 -0
- package/dist/src/sim/weapon_dynamics.d.ts +102 -0
- package/dist/src/sim/weapon_dynamics.js +142 -0
- package/dist/src/sim/weather.d.ts +95 -0
- package/dist/src/sim/weather.js +105 -0
- package/dist/src/sim/world.d.ts +52 -0
- package/dist/src/sim/world.js +1 -0
- package/dist/src/sim/wound-aging.d.ts +120 -0
- package/dist/src/sim/wound-aging.js +223 -0
- package/dist/src/species.d.ts +106 -0
- package/dist/src/species.js +664 -0
- package/dist/src/story-arcs.d.ts +17 -0
- package/dist/src/story-arcs.js +276 -0
- package/dist/src/tech-diffusion.d.ts +80 -0
- package/dist/src/tech-diffusion.js +185 -0
- package/dist/src/traits.d.ts +25 -0
- package/dist/src/traits.js +178 -0
- package/dist/src/types.d.ts +117 -0
- package/dist/src/types.js +1 -0
- package/dist/src/units.d.ts +41 -0
- package/dist/src/units.js +64 -0
- package/dist/src/weapons.d.ts +20 -0
- package/dist/src/weapons.js +824 -0
- package/dist/src/world-generation.d.ts +52 -0
- package/dist/src/world-generation.js +301 -0
- package/package.json +74 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// src/faction.ts — Phase 24: Faction & Reputation System
|
|
2
|
+
//
|
|
3
|
+
// Tracks faction membership, inter-faction standing, entity reputation, and
|
|
4
|
+
// the witness system that propagates reputation deltas from combat events.
|
|
5
|
+
//
|
|
6
|
+
// No kernel import — pure data-management module.
|
|
7
|
+
import { SCALE, q, clampQ } from "./units.js";
|
|
8
|
+
import { TraceKinds } from "./sim/kinds.js";
|
|
9
|
+
import { canDetect, DEFAULT_SENSORY_ENV } from "./sim/sensory.js";
|
|
10
|
+
// ── Standing constants ────────────────────────────────────────────────────────
|
|
11
|
+
export const STANDING_EXALTED = q(1.0); // Intra-faction default
|
|
12
|
+
export const STANDING_ALLY = q(0.70); // Allied faction default
|
|
13
|
+
export const STANDING_NEUTRAL = q(0.50); // Unknown faction default
|
|
14
|
+
export const STANDING_RIVAL = q(0.20); // Rival faction default
|
|
15
|
+
export const STANDING_KOS = q(0.0); // Kill on sight
|
|
16
|
+
/** Standing below this → AI treats target as hostile. */
|
|
17
|
+
export const STANDING_HOSTILE_THRESHOLD = q(0.30);
|
|
18
|
+
/** Standing above this → AI will not initiate combat. */
|
|
19
|
+
export const STANDING_FRIENDLY_THRESHOLD = q(0.70);
|
|
20
|
+
/** Minimum detection quality for an entity to witness an event. */
|
|
21
|
+
export const WITNESS_DETECTION_THRESHOLD = q(0.60);
|
|
22
|
+
// ── Witness event delta magnitudes ────────────────────────────────────────────
|
|
23
|
+
const DELTA_KILL = q(-0.15);
|
|
24
|
+
const DELTA_ASSAULT = q(-0.05);
|
|
25
|
+
const DELTA_AID = q(0.08);
|
|
26
|
+
// ── Map-aware serialisation helpers ──────────────────────────────────────────
|
|
27
|
+
const MAP_MARKER = "__ananke_map__";
|
|
28
|
+
const SET_MARKER = "__ananke_set__";
|
|
29
|
+
function replacer(_key, value) {
|
|
30
|
+
if (value instanceof Map) {
|
|
31
|
+
return { [MAP_MARKER]: true, entries: [...value.entries()] };
|
|
32
|
+
}
|
|
33
|
+
if (value instanceof Set) {
|
|
34
|
+
return { [SET_MARKER]: true, values: [...value.values()] };
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
function reviver(_key, value) {
|
|
39
|
+
if (value !== null && typeof value === "object") {
|
|
40
|
+
const v = value;
|
|
41
|
+
if (v[MAP_MARKER] === true) {
|
|
42
|
+
return new Map(v.entries);
|
|
43
|
+
}
|
|
44
|
+
if (v[SET_MARKER] === true) {
|
|
45
|
+
return new Set(v.values);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* Create a FactionRegistry pre-populated with rival/ally default standings.
|
|
53
|
+
*
|
|
54
|
+
* Only direct relations need to be specified; symmetric standings are NOT
|
|
55
|
+
* applied automatically (enemy of A is not necessarily enemy of B).
|
|
56
|
+
*/
|
|
57
|
+
export function createFactionRegistry(factions) {
|
|
58
|
+
const factionMap = new Map(factions.map(f => [f.id, f]));
|
|
59
|
+
const globalStanding = new Map();
|
|
60
|
+
for (const f of factions) {
|
|
61
|
+
const row = new Map();
|
|
62
|
+
for (const rival of f.rivals)
|
|
63
|
+
row.set(rival, STANDING_RIVAL);
|
|
64
|
+
for (const ally of f.allies)
|
|
65
|
+
row.set(ally, STANDING_ALLY);
|
|
66
|
+
globalStanding.set(f.id, row);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
factions: factionMap,
|
|
70
|
+
globalStanding,
|
|
71
|
+
entityReputations: new Map(),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// ── Standing computation ──────────────────────────────────────────────────────
|
|
75
|
+
/**
|
|
76
|
+
* Compute effective standing of entity `a` toward entity `b`.
|
|
77
|
+
*
|
|
78
|
+
* Priority (highest first):
|
|
79
|
+
* 1. Same faction → STANDING_EXALTED
|
|
80
|
+
* 2. Entity-level reputation (`registry.entityReputations.get(a.id)?.get(b.faction)`)
|
|
81
|
+
* combined with faction default — max of the two is used.
|
|
82
|
+
* 3. Global faction-to-faction standing
|
|
83
|
+
* 4. Rival / ally default from faction definition
|
|
84
|
+
* 5. STANDING_NEUTRAL (q(0.50)) for all unknown combinations
|
|
85
|
+
*/
|
|
86
|
+
export function effectiveStanding(registry, a, b) {
|
|
87
|
+
const aFaction = a.faction;
|
|
88
|
+
const bFaction = b.faction;
|
|
89
|
+
// Same faction → exalted
|
|
90
|
+
if (aFaction && bFaction && aFaction === bFaction)
|
|
91
|
+
return STANDING_EXALTED;
|
|
92
|
+
// Entity-level reputation of a toward b's faction
|
|
93
|
+
const personalQ = bFaction
|
|
94
|
+
? registry.entityReputations.get(a.id)?.get(bFaction)
|
|
95
|
+
: undefined;
|
|
96
|
+
// Faction-level standing of a's faction toward b's faction
|
|
97
|
+
let factionQ;
|
|
98
|
+
if (aFaction && bFaction) {
|
|
99
|
+
factionQ = registry.globalStanding.get(aFaction)?.get(bFaction);
|
|
100
|
+
}
|
|
101
|
+
// Combined: max of personal and faction (most favourable wins)
|
|
102
|
+
if (personalQ !== undefined && factionQ !== undefined) {
|
|
103
|
+
return Math.max(personalQ, factionQ);
|
|
104
|
+
}
|
|
105
|
+
if (personalQ !== undefined)
|
|
106
|
+
return personalQ;
|
|
107
|
+
if (factionQ !== undefined)
|
|
108
|
+
return factionQ;
|
|
109
|
+
return STANDING_NEUTRAL;
|
|
110
|
+
}
|
|
111
|
+
// ── Witness event application ─────────────────────────────────────────────────
|
|
112
|
+
/**
|
|
113
|
+
* Apply a witness event: adjust the actor's standing within the specified faction.
|
|
114
|
+
*
|
|
115
|
+
* Deltas are clamped to [0, SCALE.Q]. A kill of a faction member reduces the
|
|
116
|
+
* actor's standing with that faction; aiding a member increases it.
|
|
117
|
+
*/
|
|
118
|
+
export function applyWitnessEvent(registry, event) {
|
|
119
|
+
let reps = registry.entityReputations.get(event.actorId);
|
|
120
|
+
if (!reps) {
|
|
121
|
+
reps = new Map();
|
|
122
|
+
registry.entityReputations.set(event.actorId, reps);
|
|
123
|
+
}
|
|
124
|
+
const current = reps.get(event.factionId) ?? STANDING_NEUTRAL;
|
|
125
|
+
reps.set(event.factionId, clampQ(current + event.delta, 0, SCALE.Q));
|
|
126
|
+
}
|
|
127
|
+
// ── Witness extraction ────────────────────────────────────────────────────────
|
|
128
|
+
/**
|
|
129
|
+
* Scan a TraceEvent stream and produce WitnessEvents for reputation-relevant
|
|
130
|
+
* actions (kills, assaults, aid).
|
|
131
|
+
*
|
|
132
|
+
* Only events where at least one bystander entity (not the actor or target) can
|
|
133
|
+
* detect the actor (`detectionQ ≥ WITNESS_DETECTION_THRESHOLD`) are included.
|
|
134
|
+
*
|
|
135
|
+
* Deduplication: at most one event per (actorId, eventType) per tick.
|
|
136
|
+
*
|
|
137
|
+
* @param factions Map of entityId → factionId for the current scenario.
|
|
138
|
+
*/
|
|
139
|
+
export function extractWitnessEvents(events, world, factions) {
|
|
140
|
+
// First pass: collect which entities die each tick
|
|
141
|
+
const deaths = new Set();
|
|
142
|
+
for (const ev of events) {
|
|
143
|
+
if (ev.kind === TraceKinds.Death) {
|
|
144
|
+
deaths.add(`${ev.entityId}:${ev.tick}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const results = [];
|
|
148
|
+
const seen = new Set(); // dedupKey = `${actorId}:${eventType}:${tick}`
|
|
149
|
+
for (const ev of events) {
|
|
150
|
+
let actorId;
|
|
151
|
+
let targetId;
|
|
152
|
+
let eventType;
|
|
153
|
+
let delta;
|
|
154
|
+
if (ev.kind === TraceKinds.Attack && !ev.blocked && !ev.parried && ev.energy_J > 0) {
|
|
155
|
+
actorId = ev.attackerId;
|
|
156
|
+
targetId = ev.targetId;
|
|
157
|
+
const isKill = deaths.has(`${ev.targetId}:${ev.tick}`);
|
|
158
|
+
eventType = isKill ? "kill" : "assault";
|
|
159
|
+
delta = isKill ? DELTA_KILL : DELTA_ASSAULT;
|
|
160
|
+
}
|
|
161
|
+
else if (ev.kind === TraceKinds.TreatmentApplied) {
|
|
162
|
+
actorId = ev.treaterId;
|
|
163
|
+
targetId = ev.targetId;
|
|
164
|
+
eventType = "aid";
|
|
165
|
+
delta = DELTA_AID;
|
|
166
|
+
}
|
|
167
|
+
if (actorId === undefined || targetId === undefined || !eventType || delta === undefined) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const dedupKey = `${actorId}:${eventType}:${ev.tick}`;
|
|
171
|
+
if (seen.has(dedupKey))
|
|
172
|
+
continue;
|
|
173
|
+
// Faction that cares: the target's faction
|
|
174
|
+
const targetFactionId = factions.get(targetId);
|
|
175
|
+
if (!targetFactionId)
|
|
176
|
+
continue;
|
|
177
|
+
// Check for at least one bystander witness
|
|
178
|
+
const actor = world.entities.find(e => e.id === actorId);
|
|
179
|
+
if (!actor)
|
|
180
|
+
continue;
|
|
181
|
+
let hasWitness = false;
|
|
182
|
+
for (const witness of world.entities) {
|
|
183
|
+
if (witness.id === actorId || witness.id === targetId)
|
|
184
|
+
continue;
|
|
185
|
+
if (witness.injury.dead)
|
|
186
|
+
continue;
|
|
187
|
+
if (canDetect(witness, actor, DEFAULT_SENSORY_ENV) >= WITNESS_DETECTION_THRESHOLD) {
|
|
188
|
+
hasWitness = true;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!hasWitness)
|
|
193
|
+
continue;
|
|
194
|
+
seen.add(dedupKey);
|
|
195
|
+
results.push({
|
|
196
|
+
actorId,
|
|
197
|
+
targetId,
|
|
198
|
+
eventType,
|
|
199
|
+
factionId: targetFactionId,
|
|
200
|
+
delta,
|
|
201
|
+
tick: ev.tick,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return results;
|
|
205
|
+
}
|
|
206
|
+
// ── Faction-level standing mutation ──────────────────────────────────────────
|
|
207
|
+
/**
|
|
208
|
+
* Adjust the global faction-to-faction standing of `factionAId` toward
|
|
209
|
+
* `factionBId` by `delta`, clamped to [0, SCALE.Q].
|
|
210
|
+
*
|
|
211
|
+
* Used by the Polity diplomacy system (Phase 61) to apply `standingDelta`
|
|
212
|
+
* from `resolveDiplomacy`. The relation is one-directional; call twice with
|
|
213
|
+
* swapped arguments for a symmetric update.
|
|
214
|
+
*/
|
|
215
|
+
export function applyFactionStanding(registry, factionAId, factionBId, delta) {
|
|
216
|
+
let row = registry.globalStanding.get(factionAId);
|
|
217
|
+
if (!row) {
|
|
218
|
+
row = new Map();
|
|
219
|
+
registry.globalStanding.set(factionAId, row);
|
|
220
|
+
}
|
|
221
|
+
const current = row.get(factionBId) ?? STANDING_NEUTRAL;
|
|
222
|
+
row.set(factionBId, clampQ(current + delta, 0, SCALE.Q));
|
|
223
|
+
}
|
|
224
|
+
// ── Serialisation ─────────────────────────────────────────────────────────────
|
|
225
|
+
/**
|
|
226
|
+
* Serialise a FactionRegistry to a JSON string.
|
|
227
|
+
* Handles all nested Map and Set fields (rivals, allies, globalStanding, entityReputations).
|
|
228
|
+
*/
|
|
229
|
+
export function serialiseFactionRegistry(registry) {
|
|
230
|
+
return JSON.stringify(registry, replacer);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Deserialise a FactionRegistry from a JSON string produced by `serialiseFactionRegistry`.
|
|
234
|
+
*/
|
|
235
|
+
export function deserialiseFactionRegistry(json) {
|
|
236
|
+
return JSON.parse(json, reviver);
|
|
237
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { IndividualAttributes } from "./types.js";
|
|
2
|
+
import type { Archetype } from "./archetypes.js";
|
|
3
|
+
/**
|
|
4
|
+
* Signed bias applied to a character-generation axis, range [−1, 1].
|
|
5
|
+
*
|
|
6
|
+
* `+1` strongly skews toward the high end of the archetype's natural spread;
|
|
7
|
+
* `−1` toward the low end. Values outside [−1, 1] are clamped internally.
|
|
8
|
+
* A biased character is still drawn from the population — just from a
|
|
9
|
+
* different part of the tail — so physical plausibility is preserved.
|
|
10
|
+
*
|
|
11
|
+
* Fields map to these generation axes:
|
|
12
|
+
* `strength` peakForce_N, peakPower_W, continuousPower_W, actuatorScale
|
|
13
|
+
* `speed` reactionTime_s (positive bias → faster; i.e. lower time)
|
|
14
|
+
* `resilience` distressTolerance, shockTolerance, concussionTolerance,
|
|
15
|
+
* surface/bulk/structureIntegrity, recoveryRate
|
|
16
|
+
* (positive bias also reduces fatigueRate)
|
|
17
|
+
* `agility` controlQuality, fineControl, stability
|
|
18
|
+
* `size` stature_m, mass_kg (also influences reach)
|
|
19
|
+
*
|
|
20
|
+
* Note: per-individual cognitive variance (`intellect` bias) is reserved for
|
|
21
|
+
* a future phase once `Archetype.cognition` gains per-individual draws.
|
|
22
|
+
*/
|
|
23
|
+
export interface NarrativeBias {
|
|
24
|
+
/** Biases physical force and power output. */
|
|
25
|
+
strength?: number;
|
|
26
|
+
/** Biases reaction speed. Positive = faster (lower reactionTime_s). */
|
|
27
|
+
speed?: number;
|
|
28
|
+
/** Biases damage tolerance and recovery. Positive = tougher. */
|
|
29
|
+
resilience?: number;
|
|
30
|
+
/** Biases motor control precision and stability. */
|
|
31
|
+
agility?: number;
|
|
32
|
+
/** Biases body size (stature and mass). */
|
|
33
|
+
size?: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function generateIndividual(seedU32: number, arch: Archetype, bias?: NarrativeBias): IndividualAttributes;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Morphology scaling philosophy:
|
|
3
|
+
|
|
4
|
+
We intentionally damp size → strength scaling.
|
|
5
|
+
|
|
6
|
+
Real biology:
|
|
7
|
+
- strength ∝ cross-section (~mass^(2/3))
|
|
8
|
+
- mass ∝ volume
|
|
9
|
+
- energy cost grows faster than usable force
|
|
10
|
+
|
|
11
|
+
Gameplay:
|
|
12
|
+
- prevents giants from dominating
|
|
13
|
+
- keeps small entities viable
|
|
14
|
+
- allows cross-species balance
|
|
15
|
+
|
|
16
|
+
Therefore:
|
|
17
|
+
Most morphology scaling uses PARTIAL influence
|
|
18
|
+
(~20–35% of raw geometric scaling)
|
|
19
|
+
*/
|
|
20
|
+
import { makeRng } from "./rng.js";
|
|
21
|
+
import { SCALE, clampQ, q, qMul, mulDiv } from "./units.js";
|
|
22
|
+
import { triSym, biasedTriSym, mulFromVariation, skewUp } from "./dist.js";
|
|
23
|
+
// Math.cos is allowed here: generation path, not simulation path.
|
|
24
|
+
function halfArcCosQ(arcDeg) {
|
|
25
|
+
const halfRad = (arcDeg / 2) * (Math.PI / 180);
|
|
26
|
+
return Math.round(Math.cos(halfRad) * SCALE.Q);
|
|
27
|
+
}
|
|
28
|
+
function applyMultI32(base, multQ) {
|
|
29
|
+
return mulDiv(base, multQ, SCALE.Q);
|
|
30
|
+
}
|
|
31
|
+
function clampI32(x, lo, hi) {
|
|
32
|
+
return Math.max(lo, Math.min(hi, x));
|
|
33
|
+
}
|
|
34
|
+
function sqrtNear1Q(mult) {
|
|
35
|
+
return (mult + SCALE.Q) >>> 1;
|
|
36
|
+
}
|
|
37
|
+
export function generateIndividual(seedU32, arch, bias) {
|
|
38
|
+
const rng = makeRng(seedU32 >>> 0, SCALE.Q);
|
|
39
|
+
// Convenience: biasedTriSym(rng, 0) === triSym(rng), so unbiased calls
|
|
40
|
+
// are identical to the previous behaviour when bias is undefined.
|
|
41
|
+
const sz = bias?.size ?? 0;
|
|
42
|
+
const str = bias?.strength ?? 0;
|
|
43
|
+
const spd = bias?.speed ?? 0;
|
|
44
|
+
const res = bias?.resilience ?? 0;
|
|
45
|
+
const agi = bias?.agility ?? 0;
|
|
46
|
+
const statureMult = mulFromVariation(biasedTriSym(rng, sz), arch.statureVar);
|
|
47
|
+
const massMult = mulFromVariation(biasedTriSym(rng, sz), arch.massVar);
|
|
48
|
+
const reachMult = mulFromVariation(biasedTriSym(rng, sz), arch.reachVar);
|
|
49
|
+
const actuatorScaleBase = mulFromVariation(biasedTriSym(rng, str), arch.actuatorScaleVar);
|
|
50
|
+
// Combine stature + mass into a single “size composite”.
|
|
51
|
+
// We use sqrt scaling to avoid extreme linear growth:
|
|
52
|
+
// - doubling mass should NOT double strength directly
|
|
53
|
+
// - tall + heavy should scale sub-linearly
|
|
54
|
+
const sizeComposite = qMul(sqrtNear1Q(statureMult), sqrtNear1Q(massMult));
|
|
55
|
+
/*
|
|
56
|
+
Actuator scaling rule:
|
|
57
|
+
|
|
58
|
+
We do NOT apply full sizeComposite directly to force/power.
|
|
59
|
+
Instead we apply only ~25% of size deviation from baseline.
|
|
60
|
+
|
|
61
|
+
Why:
|
|
62
|
+
- Prevent giant entities becoming absurdly strong
|
|
63
|
+
- Prevent small entities becoming unusably weak
|
|
64
|
+
- Maintain cross-species balance
|
|
65
|
+
- Keep simulation numerically stable
|
|
66
|
+
|
|
67
|
+
Formula:
|
|
68
|
+
effectiveScale = 1 + (sizeComposite - 1) * 1.34
|
|
69
|
+
|
|
70
|
+
51% geometric scaling (damped).
|
|
71
|
+
*/
|
|
72
|
+
const actuatorScale = clampQ(qMul(actuatorScaleBase, (SCALE.Q + mulDiv(sizeComposite - SCALE.Q, q(1.34), SCALE.Q))), q(0.6), // lower bound: still functional
|
|
73
|
+
q(1.8) // upper bound: avoid runaway strength
|
|
74
|
+
);
|
|
75
|
+
const structureScaleBase = mulFromVariation(biasedTriSym(rng, res), arch.structureScaleVar);
|
|
76
|
+
const structureScale = clampQ(qMul(structureScaleBase, (SCALE.Q + ((sizeComposite - SCALE.Q) >>> 3))), q(0.7), q(2.0));
|
|
77
|
+
const stature_m = applyMultI32(arch.stature_m, statureMult);
|
|
78
|
+
const mass_kg = applyMultI32(arch.mass_kg, massMult);
|
|
79
|
+
const actuatorFracVar = mulFromVariation(biasedTriSym(rng, str), arch.actuatorMassVar);
|
|
80
|
+
const actuatorFrac = clampQ(qMul(arch.actuatorMassFrac, actuatorFracVar), q(0.15), q(0.70));
|
|
81
|
+
const actuatorMass_kg_raw = mulDiv(mass_kg, actuatorFrac, SCALE.Q);
|
|
82
|
+
const actuatorMass_kg = clampI32(actuatorMass_kg_raw, mulDiv(mass_kg, q(0.15), SCALE.Q), mulDiv(mass_kg, q(0.70), SCALE.Q));
|
|
83
|
+
const forceRand = mulFromVariation(biasedTriSym(rng, str), arch.peakForceVar);
|
|
84
|
+
const forceCouple = clampQ(qMul(actuatorScale, (SCALE.Q + ((actuatorFrac - arch.actuatorMassFrac) >> 1))), q(0.6), q(2.2));
|
|
85
|
+
const peakForceMult = clampQ(qMul(forceRand, forceCouple), q(0.5), q(2.5));
|
|
86
|
+
const powerRand = mulFromVariation(biasedTriSym(rng, str), arch.peakPowerVar);
|
|
87
|
+
const powerMult = clampQ(skewUp(qMul(powerRand, actuatorScale), 1), q(0.5), q(3.0));
|
|
88
|
+
const contRand = mulFromVariation(biasedTriSym(rng, str), arch.continuousPowerVar);
|
|
89
|
+
const contMult = clampQ(qMul(contRand, sqrtNear1Q(actuatorFrac)), q(0.4), q(3.0));
|
|
90
|
+
const reserveRand = mulFromVariation(biasedTriSym(rng, res), arch.reserveEnergyVar);
|
|
91
|
+
const reserveMult = clampQ(qMul(reserveRand, sqrtNear1Q(actuatorFrac)), q(0.3), q(4.0));
|
|
92
|
+
const effMult = mulFromVariation(biasedTriSym(rng, str), arch.efficiencyVar);
|
|
93
|
+
const conversionEfficiency = clampQ(qMul(arch.conversionEfficiency, effMult), q(0.45), q(0.98));
|
|
94
|
+
const peakForce_N = applyMultI32(arch.peakForce_N, peakForceMult);
|
|
95
|
+
const peakPower_W = applyMultI32(arch.peakPower_W, powerMult);
|
|
96
|
+
const continuousPower_W = applyMultI32(arch.continuousPower_W, contMult);
|
|
97
|
+
const reserveEnergy_J = applyMultI32(arch.reserveEnergy_J, reserveMult);
|
|
98
|
+
const controlMult = mulFromVariation(biasedTriSym(rng, agi), arch.controlVar);
|
|
99
|
+
const controlQuality = clampQ(qMul(arch.controlQuality, controlMult), q(0.15), q(0.98));
|
|
100
|
+
// speed bias is negated: +speed → shorter (faster) reactionTime
|
|
101
|
+
const reactMult = mulFromVariation(biasedTriSym(rng, -spd), arch.reactionTimeVar);
|
|
102
|
+
const reactCouple = clampQ((SCALE.Q + ((SCALE.Q - controlQuality) >>> 2)), q(0.75), q(1.30));
|
|
103
|
+
const reactionTime_s = applyMultI32(arch.reactionTime_s, qMul(reactMult, reactCouple));
|
|
104
|
+
const stability = clampQ(qMul(arch.stability, mulFromVariation(biasedTriSym(rng, agi), arch.stabilityVar)), q(0.05), q(0.99));
|
|
105
|
+
const rawFineControl = clampQ(qMul(arch.fineControl, mulFromVariation(biasedTriSym(rng, agi), arch.fineControlVar)), q(0.05), q(0.99));
|
|
106
|
+
// Phase 33: bodilyKinesthetic sets a floor on fine motor precision
|
|
107
|
+
const bkFloor = arch.cognition ? qMul(arch.cognition.bodilyKinesthetic, q(0.80)) : q(0);
|
|
108
|
+
const fineControl = clampQ(Math.max(rawFineControl, bkFloor), q(0.05), q(0.99));
|
|
109
|
+
const surfaceIntegrity = clampQ(qMul(arch.surfaceIntegrity, mulFromVariation(biasedTriSym(rng, res), arch.surfaceVar)), q(0.4), q(3.0));
|
|
110
|
+
const bulkIntegrity = clampQ(qMul(arch.bulkIntegrity, mulFromVariation(biasedTriSym(rng, res), arch.bulkVar)), q(0.4), q(3.0));
|
|
111
|
+
const structureIntegrity = clampQ(qMul(arch.structureIntegrity, mulFromVariation(biasedTriSym(rng, res), arch.structVar)), q(0.4), q(3.0));
|
|
112
|
+
const distressTolerance = clampQ(qMul(arch.distressTolerance, mulFromVariation(biasedTriSym(rng, res), arch.distressVar)), q(0.01), q(0.98));
|
|
113
|
+
const shockTolerance = clampQ(qMul(arch.shockTolerance, mulFromVariation(biasedTriSym(rng, res), arch.shockVar)), q(0.01), q(0.98));
|
|
114
|
+
const concussionTolerance = clampQ(qMul(arch.concussionTolerance, mulFromVariation(biasedTriSym(rng, res), arch.concVar)), q(0.01), q(0.98));
|
|
115
|
+
const heatTolerance = clampQ(qMul(arch.heatTolerance, mulFromVariation(triSym(rng), arch.heatVar)), q(0.01), q(0.98));
|
|
116
|
+
const coldTolerance = clampQ(qMul(arch.coldTolerance, mulFromVariation(triSym(rng), arch.coldVar)), q(0.01), q(0.98));
|
|
117
|
+
// positive resilience bias → lower fatigue rate (better endurance), so bias is negated
|
|
118
|
+
const fatigueRate = clampQ(qMul(arch.fatigueRate, mulFromVariation(biasedTriSym(rng, -res), arch.fatigueVar)), q(0.4), q(2.5));
|
|
119
|
+
const recoveryRate = clampQ(qMul(arch.recoveryRate, mulFromVariation(biasedTriSym(rng, res), arch.recoveryVar)), q(0.4), q(2.5));
|
|
120
|
+
return {
|
|
121
|
+
morphology: {
|
|
122
|
+
stature_m,
|
|
123
|
+
mass_kg,
|
|
124
|
+
actuatorMass_kg,
|
|
125
|
+
actuatorScale,
|
|
126
|
+
structureScale,
|
|
127
|
+
reachScale: reachMult,
|
|
128
|
+
},
|
|
129
|
+
performance: {
|
|
130
|
+
peakForce_N,
|
|
131
|
+
peakPower_W,
|
|
132
|
+
continuousPower_W,
|
|
133
|
+
reserveEnergy_J,
|
|
134
|
+
conversionEfficiency,
|
|
135
|
+
},
|
|
136
|
+
control: {
|
|
137
|
+
controlQuality,
|
|
138
|
+
reactionTime_s,
|
|
139
|
+
stability,
|
|
140
|
+
fineControl,
|
|
141
|
+
},
|
|
142
|
+
resilience: {
|
|
143
|
+
surfaceIntegrity,
|
|
144
|
+
bulkIntegrity,
|
|
145
|
+
structureIntegrity,
|
|
146
|
+
distressTolerance,
|
|
147
|
+
shockTolerance,
|
|
148
|
+
concussionTolerance,
|
|
149
|
+
heatTolerance,
|
|
150
|
+
coldTolerance,
|
|
151
|
+
fatigueRate,
|
|
152
|
+
recoveryRate,
|
|
153
|
+
},
|
|
154
|
+
perception: {
|
|
155
|
+
visionRange_m: arch.visionRange_m,
|
|
156
|
+
visionArcDeg: arch.visionArcDeg,
|
|
157
|
+
halfArcCosQ: halfArcCosQ(arch.visionArcDeg),
|
|
158
|
+
hearingRange_m: arch.hearingRange_m,
|
|
159
|
+
decisionLatency_s: arch.decisionLatency_s,
|
|
160
|
+
attentionDepth: arch.attentionDepth,
|
|
161
|
+
threatHorizon_m: arch.threatHorizon_m,
|
|
162
|
+
},
|
|
163
|
+
// Phase 33: pass through species-typical cognition (no per-individual variance)
|
|
164
|
+
...(arch.cognition ? { cognition: arch.cognition } : {}),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export * from "./units.js";
|
|
2
|
+
export * from "./types.js";
|
|
3
|
+
export * from "./archetypes.js";
|
|
4
|
+
export * from "./generate.js";
|
|
5
|
+
export * from "./equipment.js";
|
|
6
|
+
export * from "./sim/vec3.js";
|
|
7
|
+
export * from "./sim/condition.js";
|
|
8
|
+
export * from "./sim/injury.js";
|
|
9
|
+
export * from "./sim/entity.js";
|
|
10
|
+
export * from "./sim/commands.js";
|
|
11
|
+
export * from "./sim/kernel.js";
|
|
12
|
+
export * from "./sim/body.js";
|
|
13
|
+
export * from "./sim/world.js";
|
|
14
|
+
export * from "./model3d.js";
|
|
15
|
+
export * from "./replay.js";
|
|
16
|
+
export * from "./bridge/index.js";
|
|
17
|
+
export * from "./channels.js";
|
|
18
|
+
export * from "./traits.js";
|
|
19
|
+
export * from "./derive.js";
|
|
20
|
+
export * from "./sim/intent.js";
|
|
21
|
+
export * from "./sim/action.js";
|
|
22
|
+
export * from "./sim/combat.js";
|
|
23
|
+
export * from "./quest.js";
|
|
24
|
+
export * from "./quest-generators.js";
|
|
25
|
+
export * from "./relationships.js";
|
|
26
|
+
export * from "./relationships-effects.js";
|
|
27
|
+
export * from "./inventory.js";
|
|
28
|
+
export * from "./item-durability.js";
|
|
29
|
+
export * from "./settlement.js";
|
|
30
|
+
export * from "./settlement-services.js";
|
|
31
|
+
export * from "./chronicle.js";
|
|
32
|
+
export * from "./story-arcs.js";
|
|
33
|
+
export * from "./narrative-render.js";
|
|
34
|
+
export * from "./world-generation.js";
|
|
35
|
+
export * from "./sim/trace.js";
|
|
36
|
+
export * from "./rng.js";
|
|
37
|
+
export * from "./dist.js";
|
|
38
|
+
export * from "./lod.js";
|
|
39
|
+
export * from "./sim/impairment.js";
|
|
40
|
+
export * from "./sim/indexing.js";
|
|
41
|
+
export * from "./sim/tuning.js";
|
|
42
|
+
export * from "./sim/testing.js";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// ── Tier 1 — Stable host API ─────────────────────────────────────────────────
|
|
2
|
+
// These exports form the public integration surface. Breaking changes require
|
|
3
|
+
// a major semver bump (x.0.0) and a migration guide in CHANGELOG.md.
|
|
4
|
+
// Safe to import directly in host applications and typed as stable in STABLE_API.md.
|
|
5
|
+
export * from "./units.js"; // q(), SCALE, qMul, mulDiv — fixed-point arithmetic
|
|
6
|
+
export * from "./types.js"; // IndividualAttributes, core scalar types
|
|
7
|
+
export * from "./archetypes.js"; // Archetype, BodyPlan, built-in species presets
|
|
8
|
+
export * from "./generate.js"; // generateIndividual()
|
|
9
|
+
export * from "./equipment.js"; // WEAPONS database, EquipmentCatalogue
|
|
10
|
+
export * from "./sim/vec3.js"; // Vec3, lerpVec3, addVec3 — 3-D vector helpers
|
|
11
|
+
export * from "./sim/condition.js"; // ConditionSnapshot, condition constants
|
|
12
|
+
export * from "./sim/injury.js"; // InjuryRegion, BodyRegion, injury constants
|
|
13
|
+
export * from "./sim/entity.js"; // Entity (stable fields: id, pos, mass_kg, attributes…)
|
|
14
|
+
export * from "./sim/commands.js"; // CommandMap, EntityCommand, action verbs
|
|
15
|
+
export * from "./sim/kernel.js"; // stepWorld(), applyImpactToInjury(), applyExplosion()
|
|
16
|
+
export * from "./sim/body.js"; // BodyPlan, BodySegment, humanoid / quadruped plans
|
|
17
|
+
export * from "./sim/world.js"; // WorldState, KernelContext, createWorld()
|
|
18
|
+
export * from "./model3d.js"; // extractRigSnapshots(), deriveAnimationHints(), RigSnapshot, AnimationHints, GrapplePoseConstraint
|
|
19
|
+
export * from "./replay.js"; // ReplayRecorder, replayTo(), serializeReplay(), deserializeReplay()
|
|
20
|
+
export * from "./bridge/index.js"; // BridgeEngine, InterpolatedState, BridgeConfig — 3D renderer bridge
|
|
21
|
+
// ── Tier 2 — Advanced / experimental API ─────────────────────────────────────
|
|
22
|
+
// Tested and usable subsystems under active development. May change between
|
|
23
|
+
// minor versions (0.x.0); CHANGELOG.md will document any breaking change.
|
|
24
|
+
// Reference STABLE_API.md §Tier 2 for the full export list per module.
|
|
25
|
+
export * from "./channels.js"; // damage channel constants (BLUNT, SLASH, …)
|
|
26
|
+
export * from "./traits.js"; // trait descriptors
|
|
27
|
+
export * from "./derive.js"; // derived attribute helpers
|
|
28
|
+
export * from "./sim/intent.js"; // IntentMap, buildIntent()
|
|
29
|
+
export * from "./sim/action.js"; // ActionResult, resolveAction()
|
|
30
|
+
export * from "./sim/combat.js"; // resolveHit(), resolveParry(), applyCombat()
|
|
31
|
+
export * from "./quest.js"; // Quest, QuestObjective, questStep()
|
|
32
|
+
export * from "./quest-generators.js"; // generateQuest(), generateQuestChain()
|
|
33
|
+
export * from "./relationships.js"; // RelationshipMap, updateRelationship()
|
|
34
|
+
export * from "./relationships-effects.js"; // applyRelationshipEffect()
|
|
35
|
+
export * from "./inventory.js"; // Inventory, equipItem(), addItemToInventory()
|
|
36
|
+
export * from "./item-durability.js"; // durability helpers, resolveRepair()
|
|
37
|
+
export * from "./settlement.js"; // Settlement, stepSettlement()
|
|
38
|
+
export * from "./settlement-services.js"; // service resolution helpers
|
|
39
|
+
export * from "./chronicle.js"; // ChronicleEntry, addChronicleEntry()
|
|
40
|
+
export * from "./story-arcs.js"; // StoryArc, detectArcs()
|
|
41
|
+
export * from "./narrative-render.js"; // renderEntry(), renderChronicle(), generateNarrative()
|
|
42
|
+
export * from "./world-generation.js"; // WorldTemplate, generateWorld()
|
|
43
|
+
export * from "./sim/trace.js"; // SimTrace, traceStep() — debugging / profiling
|
|
44
|
+
// ── Tier 3 — Internal / kernel API ───────────────────────────────────────────
|
|
45
|
+
// Exported for power users and diagnostic tooling. Not stability-guaranteed;
|
|
46
|
+
// may change at any time without a changelog entry. Prefer Tier 1/2 surfaces
|
|
47
|
+
// in production host code. See STABLE_API.md §Tier 3 for rationale.
|
|
48
|
+
export * from "./rng.js"; // makeRng(), eventSeed() — RNG internals
|
|
49
|
+
export * from "./dist.js"; // distribution primitives
|
|
50
|
+
export * from "./lod.js"; // level-of-detail helpers
|
|
51
|
+
export * from "./sim/impairment.js"; // low-level impairment accumulators
|
|
52
|
+
export * from "./sim/indexing.js"; // SpatialIndex internals
|
|
53
|
+
export * from "./sim/tuning.js"; // kernel tuning constants (may be adjusted)
|
|
54
|
+
export * from "./sim/testing.js"; // mkHumanoidEntity() and other test helpers
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Q } from "./units.js";
|
|
2
|
+
import type { Entity } from "./sim/entity.js";
|
|
3
|
+
import type { CampaignState } from "./campaign.js";
|
|
4
|
+
import type { RelationshipGraph } from "./relationships.js";
|
|
5
|
+
export interface InheritanceSpec {
|
|
6
|
+
deceasedId: number;
|
|
7
|
+
heirId: number;
|
|
8
|
+
/**
|
|
9
|
+
* Fraction of relationship trust / affinity that passes to the heir.
|
|
10
|
+
* q(1.0) = full copy; q(0.50) = half strength; q(0) = no inheritance.
|
|
11
|
+
* Default: q(0.50).
|
|
12
|
+
*/
|
|
13
|
+
relationshipTransferRate_Q?: Q;
|
|
14
|
+
}
|
|
15
|
+
export interface InheritanceReport {
|
|
16
|
+
/** Number of loadout items moved from deceased to heir. */
|
|
17
|
+
itemsTransferred: number;
|
|
18
|
+
/** Number of new relationship entries created for the heir. */
|
|
19
|
+
relationshipsTransferred: number;
|
|
20
|
+
/** Inventory items (itemId → count) transferred from deceased to heir. */
|
|
21
|
+
inventoryTransferred: Map<string, number>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Move all loadout items from deceased to heir.
|
|
25
|
+
* Heir's existing items are preserved (deceased's items are appended).
|
|
26
|
+
* Deceased's loadout is cleared.
|
|
27
|
+
*
|
|
28
|
+
* @returns Number of items transferred.
|
|
29
|
+
*/
|
|
30
|
+
export declare function transferEquipment(deceased: Entity, heir: Entity): number;
|
|
31
|
+
/**
|
|
32
|
+
* Partially copy the deceased's relationships to the heir.
|
|
33
|
+
*
|
|
34
|
+
* For each relationship R(deceased, X):
|
|
35
|
+
* heir's trust_Q = R.trust_Q × transferRate_Q
|
|
36
|
+
* heir's affinity_Q = |R.affinity_Q| × transferRate_Q (sign preserved)
|
|
37
|
+
*
|
|
38
|
+
* Existing heir–X relationships are not overwritten.
|
|
39
|
+
* The deceased's relationships are left in the graph unmodified.
|
|
40
|
+
*
|
|
41
|
+
* @returns Number of new heir relationships created.
|
|
42
|
+
*/
|
|
43
|
+
export declare function transferRelationships(graph: RelationshipGraph, deceasedId: number, heirId: number, transferRate_Q: Q): number;
|
|
44
|
+
/**
|
|
45
|
+
* Transfer all campaign inventory items from deceased to heir.
|
|
46
|
+
* Stacks merge: heir's existing counts are summed with deceased's amounts.
|
|
47
|
+
* The deceased's campaign inventory entry is deleted after transfer.
|
|
48
|
+
*
|
|
49
|
+
* @returns Map of transferred items (itemId → count transferred).
|
|
50
|
+
*/
|
|
51
|
+
export declare function transferInventory(campaign: CampaignState, deceasedId: number, heirId: number): Map<string, number>;
|
|
52
|
+
/**
|
|
53
|
+
* Apply the full inheritance process when a character dies and an heir takes over.
|
|
54
|
+
*
|
|
55
|
+
* Steps performed:
|
|
56
|
+
* 1. Transfers loadout equipment from deceased to heir entity.
|
|
57
|
+
* 2. Transfers campaign inventory (deceased → heir, with stack merging).
|
|
58
|
+
* 3. Partially transfers relationships (if `graph` is provided).
|
|
59
|
+
* 4. Moves the deceased's campaign location to the heir.
|
|
60
|
+
* 5. Registers the heir in the campaign; removes the deceased.
|
|
61
|
+
* 6. Logs the event to `campaign.log`.
|
|
62
|
+
*
|
|
63
|
+
* Both deceased (via `campaign.entities`) and heir (provided directly) must be
|
|
64
|
+
* supplied. The deceased entity is updated in-place before being removed so
|
|
65
|
+
* that equipment is properly cleared.
|
|
66
|
+
*
|
|
67
|
+
* @returns InheritanceReport with counts of transferred items and relationships.
|
|
68
|
+
*/
|
|
69
|
+
export declare function applyInheritance(campaign: CampaignState, graph: RelationshipGraph | undefined, spec: InheritanceSpec, heir: Entity): InheritanceReport;
|