@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,82 @@
|
|
|
1
|
+
import type { BodySegment } from "../sim/bodyplan.js";
|
|
2
|
+
import { type Q } from "../units.js";
|
|
3
|
+
import type { CompiledAnatomyModel, SegmentCoverageProfile, SegmentId, SegmentSelector, SegmentTargetProfile } from "./anatomy-contracts.js";
|
|
4
|
+
export interface FunctionalHealthSummary {
|
|
5
|
+
mobility: {
|
|
6
|
+
structural: Q;
|
|
7
|
+
internal: Q;
|
|
8
|
+
fracture: Q;
|
|
9
|
+
};
|
|
10
|
+
manipulation: {
|
|
11
|
+
structural: Q;
|
|
12
|
+
internal: Q;
|
|
13
|
+
fracture: Q;
|
|
14
|
+
};
|
|
15
|
+
cns: {
|
|
16
|
+
structural: Q;
|
|
17
|
+
internal: Q;
|
|
18
|
+
fracture: Q;
|
|
19
|
+
};
|
|
20
|
+
senses: {
|
|
21
|
+
structural: Q;
|
|
22
|
+
internal: Q;
|
|
23
|
+
fracture: Q;
|
|
24
|
+
};
|
|
25
|
+
respiration: {
|
|
26
|
+
structural: Q;
|
|
27
|
+
internal: Q;
|
|
28
|
+
fracture: Q;
|
|
29
|
+
};
|
|
30
|
+
circulation: {
|
|
31
|
+
structural: Q;
|
|
32
|
+
internal: Q;
|
|
33
|
+
fracture: Q;
|
|
34
|
+
};
|
|
35
|
+
cognition: {
|
|
36
|
+
structural: Q;
|
|
37
|
+
internal: Q;
|
|
38
|
+
fracture: Q;
|
|
39
|
+
};
|
|
40
|
+
coordination: {
|
|
41
|
+
structural: Q;
|
|
42
|
+
internal: Q;
|
|
43
|
+
fracture: Q;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export interface SegmentDamageLike {
|
|
47
|
+
readonly surfaceDamage?: number;
|
|
48
|
+
readonly internalDamage?: number;
|
|
49
|
+
readonly structuralDamage?: number;
|
|
50
|
+
readonly permanentDamage?: number;
|
|
51
|
+
readonly fractured?: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface InjuryStateLike {
|
|
54
|
+
readonly byRegion: Record<string, SegmentDamageLike | undefined>;
|
|
55
|
+
}
|
|
56
|
+
export interface AnatomyHelperRegistry {
|
|
57
|
+
readonly selectors: {
|
|
58
|
+
selectSegmentIds(selector: SegmentSelector): readonly SegmentId[];
|
|
59
|
+
selectSegments(selector: SegmentSelector): readonly BodySegment[];
|
|
60
|
+
};
|
|
61
|
+
readonly targeting?: {
|
|
62
|
+
sampleSegmentId(profileId: string, roll01: number): SegmentId;
|
|
63
|
+
};
|
|
64
|
+
readonly coverage?: {
|
|
65
|
+
coveredSegmentIds(profileId: string): readonly SegmentId[];
|
|
66
|
+
coversSegmentId(profileId: string, segmentId: SegmentId): boolean;
|
|
67
|
+
};
|
|
68
|
+
readonly functionalDamage?: {
|
|
69
|
+
summarize(injury: InjuryStateLike): FunctionalHealthSummary;
|
|
70
|
+
isFunctionDisabled(injury: InjuryStateLike, functionId: string, threshold?: number): boolean;
|
|
71
|
+
};
|
|
72
|
+
readonly humanoidAliases?: {
|
|
73
|
+
resolve(alias: keyof NonNullable<CompiledAnatomyModel["contracts"]["humanoidTargeting"]>): readonly SegmentId[];
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export declare function createAnatomyHelpers(model: CompiledAnatomyModel): AnatomyHelperRegistry;
|
|
77
|
+
export declare function resolveSelectorIds(model: CompiledAnatomyModel, selector: SegmentSelector): readonly SegmentId[];
|
|
78
|
+
export declare function summarizeFunctionalHealth(model: CompiledAnatomyModel, injury: InjuryStateLike): FunctionalHealthSummary;
|
|
79
|
+
export declare function functionHealth(model: CompiledAnatomyModel, injury: InjuryStateLike, functionId: string): number;
|
|
80
|
+
export declare function segmentHealth(region: SegmentDamageLike | undefined): number;
|
|
81
|
+
export declare function sampleProfile(model: CompiledAnatomyModel, profile: SegmentTargetProfile, roll01: number): SegmentId;
|
|
82
|
+
export type { SegmentCoverageProfile };
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { q, SCALE } from "../units.js";
|
|
2
|
+
export function createAnatomyHelpers(model) {
|
|
3
|
+
const selectors = {
|
|
4
|
+
selectSegmentIds: (selector) => resolveSelectorIds(model, selector),
|
|
5
|
+
selectSegments: (selector) => resolveSelectorIds(model, selector)
|
|
6
|
+
.map((id) => model.indexes.segmentsById.get(id))
|
|
7
|
+
.filter((seg) => seg !== undefined),
|
|
8
|
+
};
|
|
9
|
+
const targeting = model.capabilities.targetingModel !== "segments"
|
|
10
|
+
? {
|
|
11
|
+
sampleSegmentId: (profileId, roll01) => sampleProfile(model, requireTargetProfile(model, profileId), roll01),
|
|
12
|
+
}
|
|
13
|
+
: undefined;
|
|
14
|
+
const coverage = model.capabilities.supportsShieldCoverage
|
|
15
|
+
? {
|
|
16
|
+
coveredSegmentIds: (profileId) => resolveCoverageProfile(model, profileId),
|
|
17
|
+
coversSegmentId: (profileId, segmentId) => resolveCoverageProfile(model, profileId).includes(segmentId),
|
|
18
|
+
}
|
|
19
|
+
: undefined;
|
|
20
|
+
const functionalDamage = model.contracts.ids.has("functionalDamage")
|
|
21
|
+
? {
|
|
22
|
+
summarize: (injury) => summarizeFunctionalHealth(model, injury),
|
|
23
|
+
isFunctionDisabled: (injury, functionId, threshold = 0.70) => functionHealth(model, injury, functionId) <= clamp01(1 - threshold),
|
|
24
|
+
}
|
|
25
|
+
: undefined;
|
|
26
|
+
const humanoidAliases = model.contracts.humanoidTargeting
|
|
27
|
+
? {
|
|
28
|
+
resolve: (alias) => model.contracts.humanoidTargeting?.[alias] ?? [],
|
|
29
|
+
}
|
|
30
|
+
: undefined;
|
|
31
|
+
return {
|
|
32
|
+
selectors,
|
|
33
|
+
...(targeting ? { targeting } : {}),
|
|
34
|
+
...(coverage ? { coverage } : {}),
|
|
35
|
+
...(functionalDamage ? { functionalDamage } : {}),
|
|
36
|
+
...(humanoidAliases ? { humanoidAliases } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function resolveSelectorIds(model, selector) {
|
|
40
|
+
let current = new Set(model.indexes.segmentsById.keys());
|
|
41
|
+
if (selector.ids)
|
|
42
|
+
current = intersect(current, new Set(selector.ids));
|
|
43
|
+
if (selector.tags) {
|
|
44
|
+
const tagMatches = new Set();
|
|
45
|
+
for (const tag of selector.tags) {
|
|
46
|
+
for (const id of model.indexes.segmentsByTag.get(tag) ?? [])
|
|
47
|
+
tagMatches.add(id);
|
|
48
|
+
}
|
|
49
|
+
current = intersect(current, tagMatches);
|
|
50
|
+
}
|
|
51
|
+
if (selector.functionIds) {
|
|
52
|
+
const fnMatches = new Set();
|
|
53
|
+
for (const fnId of selector.functionIds) {
|
|
54
|
+
for (const id of model.indexes.segmentsByFunction.get(fnId) ?? [])
|
|
55
|
+
fnMatches.add(id);
|
|
56
|
+
}
|
|
57
|
+
current = intersect(current, fnMatches);
|
|
58
|
+
}
|
|
59
|
+
if (selector.subtreeOf) {
|
|
60
|
+
current = intersect(current, new Set(model.indexes.subtreeById.get(selector.subtreeOf) ?? []));
|
|
61
|
+
}
|
|
62
|
+
if (selector.anyOf) {
|
|
63
|
+
const anyOf = new Set();
|
|
64
|
+
for (const nested of selector.anyOf) {
|
|
65
|
+
for (const id of resolveSelectorIds(model, nested))
|
|
66
|
+
anyOf.add(id);
|
|
67
|
+
}
|
|
68
|
+
current = intersect(current, anyOf);
|
|
69
|
+
}
|
|
70
|
+
if (selector.allOf) {
|
|
71
|
+
for (const nested of selector.allOf) {
|
|
72
|
+
current = intersect(current, new Set(resolveSelectorIds(model, nested)));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (selector.exclude) {
|
|
76
|
+
const excluded = new Set(resolveSelectorIds(model, selector.exclude));
|
|
77
|
+
current = difference(current, excluded);
|
|
78
|
+
}
|
|
79
|
+
return [...current];
|
|
80
|
+
}
|
|
81
|
+
export function summarizeFunctionalHealth(model, injury) {
|
|
82
|
+
return {
|
|
83
|
+
mobility: summarizeDamageGroup(model, injury, ["mobility", "locomotion"]),
|
|
84
|
+
manipulation: summarizeDamageGroup(model, injury, ["manipulation"]),
|
|
85
|
+
cns: summarizeDamageGroup(model, injury, ["cns", "cognition", "control"]),
|
|
86
|
+
senses: summarizeDamageGroup(model, injury, ["sensor", "vision", "balance"]),
|
|
87
|
+
respiration: summarizeDamageGroup(model, injury, ["respiration"]),
|
|
88
|
+
circulation: summarizeDamageGroup(model, injury, ["circulation"]),
|
|
89
|
+
cognition: summarizeDamageGroup(model, injury, ["cognition"]),
|
|
90
|
+
coordination: summarizeDamageGroup(model, injury, ["coordination", "stancePosture"]),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function summarizeDamageGroup(model, injury, functionIds) {
|
|
94
|
+
const segmentIds = new Set();
|
|
95
|
+
for (const functionId of functionIds) {
|
|
96
|
+
const ids = model.indexes.segmentsByFunction.get(functionId) ?? [];
|
|
97
|
+
for (const id of ids)
|
|
98
|
+
segmentIds.add(id);
|
|
99
|
+
}
|
|
100
|
+
const ids = [...segmentIds];
|
|
101
|
+
if (ids.length === 0) {
|
|
102
|
+
return {
|
|
103
|
+
structural: q(0),
|
|
104
|
+
internal: q(0),
|
|
105
|
+
fracture: q(0),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
let structuralSum = 0;
|
|
109
|
+
let internalSum = 0;
|
|
110
|
+
let fractureCount = 0;
|
|
111
|
+
for (const id of ids) {
|
|
112
|
+
const region = injury.byRegion[id];
|
|
113
|
+
structuralSum += region?.structuralDamage ?? 0;
|
|
114
|
+
internalSum += region?.internalDamage ?? 0;
|
|
115
|
+
if (region?.fractured)
|
|
116
|
+
fractureCount += 1;
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
structural: Math.trunc(structuralSum / ids.length),
|
|
120
|
+
internal: Math.trunc(internalSum / ids.length),
|
|
121
|
+
fracture: Math.trunc((fractureCount * SCALE.Q) / ids.length),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export function functionHealth(model, injury, functionId) {
|
|
125
|
+
const segmentIds = model.indexes.segmentsByFunction.get(functionId) ?? [];
|
|
126
|
+
if (segmentIds.length === 0)
|
|
127
|
+
return 1;
|
|
128
|
+
const contributions = [];
|
|
129
|
+
for (const segmentId of segmentIds) {
|
|
130
|
+
const augmentation = model.segmentData.get(segmentId);
|
|
131
|
+
const fn = augmentation?.functions.find(candidate => candidate.id === functionId);
|
|
132
|
+
const weight = fn?.weight ?? defaultFunctionWeight(fn?.role);
|
|
133
|
+
contributions.push(segmentHealth(injury.byRegion[segmentId]) * weight);
|
|
134
|
+
}
|
|
135
|
+
const totalWeight = segmentIds.reduce((sum, segmentId) => {
|
|
136
|
+
const augmentation = model.segmentData.get(segmentId);
|
|
137
|
+
const fn = augmentation?.functions.find(candidate => candidate.id === functionId);
|
|
138
|
+
return sum + (fn?.weight ?? defaultFunctionWeight(fn?.role));
|
|
139
|
+
}, 0);
|
|
140
|
+
if (totalWeight <= 0)
|
|
141
|
+
return average(contributions);
|
|
142
|
+
return clamp01(contributions.reduce((sum, value) => sum + value, 0) / totalWeight);
|
|
143
|
+
}
|
|
144
|
+
export function segmentHealth(region) {
|
|
145
|
+
if (!region)
|
|
146
|
+
return 1;
|
|
147
|
+
const structural = clamp01(region.structuralDamage ?? 0);
|
|
148
|
+
const internal = clamp01(region.internalDamage ?? 0);
|
|
149
|
+
const surface = clamp01(region.surfaceDamage ?? 0);
|
|
150
|
+
const permanent = clamp01(region.permanentDamage ?? 0);
|
|
151
|
+
const fracturePenalty = region.fractured ? 0.20 : 0;
|
|
152
|
+
return clamp01(1 - (structural * 0.40 + internal * 0.35 + surface * 0.15 + permanent * 0.10 + fracturePenalty));
|
|
153
|
+
}
|
|
154
|
+
export function sampleProfile(model, profile, roll01) {
|
|
155
|
+
const segments = profile.selectors.flatMap(selector => {
|
|
156
|
+
const ids = resolveSelectorIds(model, selector);
|
|
157
|
+
return ids.map(id => ({ id, weight: selector.weight }));
|
|
158
|
+
});
|
|
159
|
+
if (segments.length === 0) {
|
|
160
|
+
return fallbackSegment(model);
|
|
161
|
+
}
|
|
162
|
+
const byId = new Map();
|
|
163
|
+
for (const entry of segments) {
|
|
164
|
+
byId.set(entry.id, (byId.get(entry.id) ?? 0) + entry.weight);
|
|
165
|
+
}
|
|
166
|
+
const total = [...byId.values()].reduce((sum, value) => sum + value, 0);
|
|
167
|
+
if (total <= 0)
|
|
168
|
+
return fallbackSegment(model);
|
|
169
|
+
let cursor = clamp01(roll01) * total;
|
|
170
|
+
for (const [id, weight] of byId) {
|
|
171
|
+
if (cursor < weight)
|
|
172
|
+
return id;
|
|
173
|
+
cursor -= weight;
|
|
174
|
+
}
|
|
175
|
+
return [...byId.keys()][byId.size - 1] ?? fallbackSegment(model);
|
|
176
|
+
}
|
|
177
|
+
function resolveCoverageProfile(model, profileId) {
|
|
178
|
+
const profile = model.coverageProfiles.get(profileId);
|
|
179
|
+
if (!profile)
|
|
180
|
+
throw new Error(`Unknown coverage profile '${profileId}'.`);
|
|
181
|
+
return unique(profile.selectors.flatMap(selector => resolveSelectorIds(model, selector)));
|
|
182
|
+
}
|
|
183
|
+
function requireTargetProfile(model, profileId) {
|
|
184
|
+
const profile = model.targetProfiles.get(profileId);
|
|
185
|
+
if (!profile)
|
|
186
|
+
throw new Error(`Unknown target profile '${profileId}'.`);
|
|
187
|
+
return profile;
|
|
188
|
+
}
|
|
189
|
+
function fallbackSegment(model) {
|
|
190
|
+
return model.plan.segments[model.plan.segments.length - 1]?.id ?? "torso";
|
|
191
|
+
}
|
|
192
|
+
function defaultFunctionWeight(role) {
|
|
193
|
+
switch (role) {
|
|
194
|
+
case "primary":
|
|
195
|
+
return 1.0;
|
|
196
|
+
case "secondary":
|
|
197
|
+
return 0.6;
|
|
198
|
+
case "support":
|
|
199
|
+
return 0.35;
|
|
200
|
+
default:
|
|
201
|
+
return 1.0;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function average(values) {
|
|
205
|
+
const filtered = values.filter(v => Number.isFinite(v));
|
|
206
|
+
if (filtered.length === 0)
|
|
207
|
+
return 1;
|
|
208
|
+
return clamp01(filtered.reduce((sum, value) => sum + value, 0) / filtered.length);
|
|
209
|
+
}
|
|
210
|
+
function unique(values) {
|
|
211
|
+
return [...new Set(values)];
|
|
212
|
+
}
|
|
213
|
+
function intersect(left, right) {
|
|
214
|
+
const out = new Set();
|
|
215
|
+
for (const value of left)
|
|
216
|
+
if (right.has(value))
|
|
217
|
+
out.add(value);
|
|
218
|
+
return out;
|
|
219
|
+
}
|
|
220
|
+
function difference(left, right) {
|
|
221
|
+
const out = new Set();
|
|
222
|
+
for (const value of left)
|
|
223
|
+
if (!right.has(value))
|
|
224
|
+
out.add(value);
|
|
225
|
+
return out;
|
|
226
|
+
}
|
|
227
|
+
function clamp01(value) {
|
|
228
|
+
if (value <= 0)
|
|
229
|
+
return 0;
|
|
230
|
+
if (value >= 1)
|
|
231
|
+
return 1;
|
|
232
|
+
return value;
|
|
233
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { BodyPlan } from "../sim/bodyplan.js";
|
|
2
|
+
import type { OrganDefinition, SegmentCoverageProfile, SegmentFunctionDefinition, SegmentSelector, SegmentTargetAliasBlock, SegmentTargetProfile, TissueLayerDefinition } from "./anatomy-contracts.js";
|
|
3
|
+
export interface ExtendedBodySegmentData {
|
|
4
|
+
tags?: readonly string[];
|
|
5
|
+
tissues?: readonly TissueLayerDefinition[];
|
|
6
|
+
organs?: readonly OrganDefinition[];
|
|
7
|
+
functions?: readonly SegmentFunctionDefinition[];
|
|
8
|
+
}
|
|
9
|
+
export interface ExtendedBodyPlanDefinition extends BodyPlan {
|
|
10
|
+
symmetry?: "none" | "bilateral" | "radial";
|
|
11
|
+
segmentData?: Record<string, ExtendedBodySegmentData>;
|
|
12
|
+
targetProfiles?: readonly SegmentTargetProfile[];
|
|
13
|
+
coverageProfiles?: readonly SegmentCoverageProfile[];
|
|
14
|
+
contracts?: {
|
|
15
|
+
humanoidTargeting?: SegmentTargetAliasBlock;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface ValidationIssue {
|
|
19
|
+
readonly path: string;
|
|
20
|
+
readonly message: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ValidationResult<T> {
|
|
23
|
+
readonly ok: boolean;
|
|
24
|
+
readonly value?: T;
|
|
25
|
+
readonly issues: readonly ValidationIssue[];
|
|
26
|
+
}
|
|
27
|
+
export declare function validateExtendedBodyPlan(input: ExtendedBodyPlanDefinition): ValidationResult<ExtendedBodyPlanDefinition>;
|
|
28
|
+
export type { SegmentSelector };
|