@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.
Files changed (311) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/LICENSE +21 -0
  3. package/README.md +2199 -0
  4. package/STABLE_API.md +266 -0
  5. package/dist/src/anatomy/anatomy-compiler.d.ts +14 -0
  6. package/dist/src/anatomy/anatomy-compiler.js +277 -0
  7. package/dist/src/anatomy/anatomy-contracts.d.ts +94 -0
  8. package/dist/src/anatomy/anatomy-contracts.js +1 -0
  9. package/dist/src/anatomy/anatomy-helpers.d.ts +82 -0
  10. package/dist/src/anatomy/anatomy-helpers.js +233 -0
  11. package/dist/src/anatomy/anatomy-schema.d.ts +28 -0
  12. package/dist/src/anatomy/anatomy-schema.js +388 -0
  13. package/dist/src/anatomy/index.d.ts +4 -0
  14. package/dist/src/anatomy/index.js +4 -0
  15. package/dist/src/archetypes.d.ts +87 -0
  16. package/dist/src/archetypes.js +285 -0
  17. package/dist/src/arena.d.ts +173 -0
  18. package/dist/src/arena.js +695 -0
  19. package/dist/src/bridge/bridge-engine.d.ts +46 -0
  20. package/dist/src/bridge/bridge-engine.js +252 -0
  21. package/dist/src/bridge/index.d.ts +4 -0
  22. package/dist/src/bridge/index.js +5 -0
  23. package/dist/src/bridge/interpolation.d.ts +64 -0
  24. package/dist/src/bridge/interpolation.js +130 -0
  25. package/dist/src/bridge/mapping.d.ts +33 -0
  26. package/dist/src/bridge/mapping.js +54 -0
  27. package/dist/src/bridge/types.d.ts +94 -0
  28. package/dist/src/bridge/types.js +2 -0
  29. package/dist/src/campaign.d.ts +141 -0
  30. package/dist/src/campaign.js +235 -0
  31. package/dist/src/channels.d.ts +15 -0
  32. package/dist/src/channels.js +20 -0
  33. package/dist/src/chronicle.d.ts +124 -0
  34. package/dist/src/chronicle.js +232 -0
  35. package/dist/src/collective-activities.d.ts +154 -0
  36. package/dist/src/collective-activities.js +247 -0
  37. package/dist/src/competence/acoustic.d.ts +101 -0
  38. package/dist/src/competence/acoustic.js +242 -0
  39. package/dist/src/competence/catalogue.d.ts +30 -0
  40. package/dist/src/competence/catalogue.js +241 -0
  41. package/dist/src/competence/crafting.d.ts +35 -0
  42. package/dist/src/competence/crafting.js +88 -0
  43. package/dist/src/competence/engineering.d.ts +53 -0
  44. package/dist/src/competence/engineering.js +108 -0
  45. package/dist/src/competence/framework.d.ts +68 -0
  46. package/dist/src/competence/framework.js +694 -0
  47. package/dist/src/competence/index.d.ts +12 -0
  48. package/dist/src/competence/index.js +13 -0
  49. package/dist/src/competence/interspecies.d.ts +81 -0
  50. package/dist/src/competence/interspecies.js +108 -0
  51. package/dist/src/competence/language.d.ts +79 -0
  52. package/dist/src/competence/language.js +115 -0
  53. package/dist/src/competence/naturalist.d.ts +97 -0
  54. package/dist/src/competence/naturalist.js +187 -0
  55. package/dist/src/competence/navigation.d.ts +24 -0
  56. package/dist/src/competence/navigation.js +48 -0
  57. package/dist/src/competence/performance.d.ts +125 -0
  58. package/dist/src/competence/performance.js +210 -0
  59. package/dist/src/competence/teaching.d.ts +64 -0
  60. package/dist/src/competence/teaching.js +121 -0
  61. package/dist/src/competence/willpower.d.ts +74 -0
  62. package/dist/src/competence/willpower.js +114 -0
  63. package/dist/src/crafting/index.d.ts +55 -0
  64. package/dist/src/crafting/index.js +229 -0
  65. package/dist/src/crafting/manufacturing.d.ts +83 -0
  66. package/dist/src/crafting/manufacturing.js +165 -0
  67. package/dist/src/crafting/materials.d.ts +53 -0
  68. package/dist/src/crafting/materials.js +120 -0
  69. package/dist/src/crafting/recipes.d.ts +75 -0
  70. package/dist/src/crafting/recipes.js +233 -0
  71. package/dist/src/crafting/workshops.d.ts +61 -0
  72. package/dist/src/crafting/workshops.js +170 -0
  73. package/dist/src/debug.d.ts +86 -0
  74. package/dist/src/debug.js +76 -0
  75. package/dist/src/derive.d.ts +21 -0
  76. package/dist/src/derive.js +88 -0
  77. package/dist/src/describe.d.ts +29 -0
  78. package/dist/src/describe.js +276 -0
  79. package/dist/src/dialogue.d.ts +122 -0
  80. package/dist/src/dialogue.js +266 -0
  81. package/dist/src/dist.d.ts +20 -0
  82. package/dist/src/dist.js +39 -0
  83. package/dist/src/downtime.d.ts +89 -0
  84. package/dist/src/downtime.js +391 -0
  85. package/dist/src/economy.d.ts +116 -0
  86. package/dist/src/economy.js +182 -0
  87. package/dist/src/emotional-contagion.d.ts +142 -0
  88. package/dist/src/emotional-contagion.js +274 -0
  89. package/dist/src/equipment.d.ts +206 -0
  90. package/dist/src/equipment.js +598 -0
  91. package/dist/src/faction.d.ts +102 -0
  92. package/dist/src/faction.js +237 -0
  93. package/dist/src/generate.d.ts +35 -0
  94. package/dist/src/generate.js +166 -0
  95. package/dist/src/index.d.ts +42 -0
  96. package/dist/src/index.js +54 -0
  97. package/dist/src/inheritance.d.ts +69 -0
  98. package/dist/src/inheritance.js +136 -0
  99. package/dist/src/inventory.d.ts +194 -0
  100. package/dist/src/inventory.js +637 -0
  101. package/dist/src/item-durability.d.ts +69 -0
  102. package/dist/src/item-durability.js +308 -0
  103. package/dist/src/legend.d.ts +97 -0
  104. package/dist/src/legend.js +269 -0
  105. package/dist/src/lod.d.ts +9 -0
  106. package/dist/src/lod.js +84 -0
  107. package/dist/src/metrics.d.ts +51 -0
  108. package/dist/src/metrics.js +91 -0
  109. package/dist/src/model3d.d.ts +138 -0
  110. package/dist/src/model3d.js +214 -0
  111. package/dist/src/mythology.d.ts +101 -0
  112. package/dist/src/mythology.js +308 -0
  113. package/dist/src/narrative-render.d.ts +42 -0
  114. package/dist/src/narrative-render.js +194 -0
  115. package/dist/src/narrative-stress.d.ts +123 -0
  116. package/dist/src/narrative-stress.js +183 -0
  117. package/dist/src/narrative.d.ts +44 -0
  118. package/dist/src/narrative.js +257 -0
  119. package/dist/src/party.d.ts +70 -0
  120. package/dist/src/party.js +226 -0
  121. package/dist/src/polity.d.ts +262 -0
  122. package/dist/src/polity.js +398 -0
  123. package/dist/src/presets.d.ts +42 -0
  124. package/dist/src/presets.js +170 -0
  125. package/dist/src/progression.d.ts +170 -0
  126. package/dist/src/progression.js +256 -0
  127. package/dist/src/quest-generators.d.ts +76 -0
  128. package/dist/src/quest-generators.js +534 -0
  129. package/dist/src/quest.d.ts +239 -0
  130. package/dist/src/quest.js +520 -0
  131. package/dist/src/relationships-effects.d.ts +75 -0
  132. package/dist/src/relationships-effects.js +219 -0
  133. package/dist/src/relationships.d.ts +104 -0
  134. package/dist/src/relationships.js +347 -0
  135. package/dist/src/replay.d.ts +47 -0
  136. package/dist/src/replay.js +82 -0
  137. package/dist/src/rng.d.ts +9 -0
  138. package/dist/src/rng.js +37 -0
  139. package/dist/src/settlement-services.d.ts +67 -0
  140. package/dist/src/settlement-services.js +267 -0
  141. package/dist/src/settlement.d.ts +143 -0
  142. package/dist/src/settlement.js +419 -0
  143. package/dist/src/sim/action.d.ts +28 -0
  144. package/dist/src/sim/action.js +12 -0
  145. package/dist/src/sim/aging.d.ts +95 -0
  146. package/dist/src/sim/aging.js +243 -0
  147. package/dist/src/sim/ai/decide.d.ts +10 -0
  148. package/dist/src/sim/ai/decide.js +267 -0
  149. package/dist/src/sim/ai/perception.d.ts +12 -0
  150. package/dist/src/sim/ai/perception.js +54 -0
  151. package/dist/src/sim/ai/personality.d.ts +54 -0
  152. package/dist/src/sim/ai/personality.js +202 -0
  153. package/dist/src/sim/ai/presets.d.ts +2 -0
  154. package/dist/src/sim/ai/presets.js +28 -0
  155. package/dist/src/sim/ai/system.d.ts +6 -0
  156. package/dist/src/sim/ai/system.js +13 -0
  157. package/dist/src/sim/ai/targeting.d.ts +8 -0
  158. package/dist/src/sim/ai/targeting.js +42 -0
  159. package/dist/src/sim/ai/types.d.ts +14 -0
  160. package/dist/src/sim/ai/types.js +1 -0
  161. package/dist/src/sim/body.d.ts +9 -0
  162. package/dist/src/sim/body.js +32 -0
  163. package/dist/src/sim/bodyplan.d.ts +161 -0
  164. package/dist/src/sim/bodyplan.js +677 -0
  165. package/dist/src/sim/capability.d.ts +135 -0
  166. package/dist/src/sim/capability.js +8 -0
  167. package/dist/src/sim/combat.d.ts +21 -0
  168. package/dist/src/sim/combat.js +77 -0
  169. package/dist/src/sim/commandBuilders.d.ts +11 -0
  170. package/dist/src/sim/commandBuilders.js +39 -0
  171. package/dist/src/sim/commands.d.ts +71 -0
  172. package/dist/src/sim/commands.js +8 -0
  173. package/dist/src/sim/condition.d.ts +35 -0
  174. package/dist/src/sim/condition.js +21 -0
  175. package/dist/src/sim/cone.d.ts +40 -0
  176. package/dist/src/sim/cone.js +44 -0
  177. package/dist/src/sim/context.d.ts +68 -0
  178. package/dist/src/sim/context.js +1 -0
  179. package/dist/src/sim/density.d.ts +14 -0
  180. package/dist/src/sim/density.js +33 -0
  181. package/dist/src/sim/disease.d.ts +141 -0
  182. package/dist/src/sim/disease.js +353 -0
  183. package/dist/src/sim/entity.d.ts +251 -0
  184. package/dist/src/sim/entity.js +19 -0
  185. package/dist/src/sim/events.d.ts +25 -0
  186. package/dist/src/sim/events.js +5 -0
  187. package/dist/src/sim/explosion.d.ts +40 -0
  188. package/dist/src/sim/explosion.js +40 -0
  189. package/dist/src/sim/formation-unit.d.ts +138 -0
  190. package/dist/src/sim/formation-unit.js +197 -0
  191. package/dist/src/sim/formation.d.ts +12 -0
  192. package/dist/src/sim/formation.js +54 -0
  193. package/dist/src/sim/frontage.d.ts +30 -0
  194. package/dist/src/sim/frontage.js +84 -0
  195. package/dist/src/sim/grapple.d.ts +100 -0
  196. package/dist/src/sim/grapple.js +480 -0
  197. package/dist/src/sim/hazard.d.ts +104 -0
  198. package/dist/src/sim/hazard.js +201 -0
  199. package/dist/src/sim/hydrostatic.d.ts +58 -0
  200. package/dist/src/sim/hydrostatic.js +117 -0
  201. package/dist/src/sim/impairment.d.ts +20 -0
  202. package/dist/src/sim/impairment.js +162 -0
  203. package/dist/src/sim/indexing.d.ts +7 -0
  204. package/dist/src/sim/indexing.js +7 -0
  205. package/dist/src/sim/injury.d.ts +54 -0
  206. package/dist/src/sim/injury.js +66 -0
  207. package/dist/src/sim/intent.d.ts +26 -0
  208. package/dist/src/sim/intent.js +7 -0
  209. package/dist/src/sim/kernel.d.ts +45 -0
  210. package/dist/src/sim/kernel.js +1992 -0
  211. package/dist/src/sim/kinds.d.ts +64 -0
  212. package/dist/src/sim/kinds.js +56 -0
  213. package/dist/src/sim/knockback.d.ts +50 -0
  214. package/dist/src/sim/knockback.js +82 -0
  215. package/dist/src/sim/limb.d.ts +48 -0
  216. package/dist/src/sim/limb.js +78 -0
  217. package/dist/src/sim/medical.d.ts +32 -0
  218. package/dist/src/sim/medical.js +33 -0
  219. package/dist/src/sim/morale.d.ts +69 -0
  220. package/dist/src/sim/morale.js +92 -0
  221. package/dist/src/sim/mount.d.ts +150 -0
  222. package/dist/src/sim/mount.js +225 -0
  223. package/dist/src/sim/nutrition.d.ts +74 -0
  224. package/dist/src/sim/nutrition.js +168 -0
  225. package/dist/src/sim/occlusion.d.ts +8 -0
  226. package/dist/src/sim/occlusion.js +71 -0
  227. package/dist/src/sim/push.d.ts +11 -0
  228. package/dist/src/sim/push.js +79 -0
  229. package/dist/src/sim/ranged.d.ts +44 -0
  230. package/dist/src/sim/ranged.js +69 -0
  231. package/dist/src/sim/seeds.d.ts +3 -0
  232. package/dist/src/sim/seeds.js +16 -0
  233. package/dist/src/sim/sensory-extended.d.ts +103 -0
  234. package/dist/src/sim/sensory-extended.js +181 -0
  235. package/dist/src/sim/sensory.d.ts +38 -0
  236. package/dist/src/sim/sensory.js +109 -0
  237. package/dist/src/sim/skills.d.ts +70 -0
  238. package/dist/src/sim/skills.js +69 -0
  239. package/dist/src/sim/sleep.d.ts +107 -0
  240. package/dist/src/sim/sleep.js +215 -0
  241. package/dist/src/sim/spatial.d.ts +8 -0
  242. package/dist/src/sim/spatial.js +59 -0
  243. package/dist/src/sim/step/capability.d.ts +8 -0
  244. package/dist/src/sim/step/capability.js +77 -0
  245. package/dist/src/sim/step/concentration.d.ts +9 -0
  246. package/dist/src/sim/step/concentration.js +25 -0
  247. package/dist/src/sim/step/effects.d.ts +17 -0
  248. package/dist/src/sim/step/effects.js +96 -0
  249. package/dist/src/sim/step/energy.d.ts +3 -0
  250. package/dist/src/sim/step/energy.js +31 -0
  251. package/dist/src/sim/step/hazards.d.ts +4 -0
  252. package/dist/src/sim/step/hazards.js +19 -0
  253. package/dist/src/sim/step/injury.d.ts +10 -0
  254. package/dist/src/sim/step/injury.js +353 -0
  255. package/dist/src/sim/step/morale.d.ts +11 -0
  256. package/dist/src/sim/step/morale.js +130 -0
  257. package/dist/src/sim/step/movement.d.ts +5 -0
  258. package/dist/src/sim/step/movement.js +172 -0
  259. package/dist/src/sim/step/push.d.ts +11 -0
  260. package/dist/src/sim/step/push.js +79 -0
  261. package/dist/src/sim/step/substances.d.ts +3 -0
  262. package/dist/src/sim/step/substances.js +75 -0
  263. package/dist/src/sim/substance.d.ts +38 -0
  264. package/dist/src/sim/substance.js +57 -0
  265. package/dist/src/sim/systemic-toxicology.d.ts +109 -0
  266. package/dist/src/sim/systemic-toxicology.js +263 -0
  267. package/dist/src/sim/team.d.ts +9 -0
  268. package/dist/src/sim/team.js +37 -0
  269. package/dist/src/sim/tech.d.ts +36 -0
  270. package/dist/src/sim/tech.js +46 -0
  271. package/dist/src/sim/terrain.d.ts +121 -0
  272. package/dist/src/sim/terrain.js +141 -0
  273. package/dist/src/sim/testing.d.ts +13 -0
  274. package/dist/src/sim/testing.js +100 -0
  275. package/dist/src/sim/thermoregulation.d.ts +77 -0
  276. package/dist/src/sim/thermoregulation.js +161 -0
  277. package/dist/src/sim/tick.d.ts +3 -0
  278. package/dist/src/sim/tick.js +3 -0
  279. package/dist/src/sim/toxicology.d.ts +52 -0
  280. package/dist/src/sim/toxicology.js +104 -0
  281. package/dist/src/sim/trace.d.ts +141 -0
  282. package/dist/src/sim/trace.js +1 -0
  283. package/dist/src/sim/tuning.d.ts +16 -0
  284. package/dist/src/sim/tuning.js +42 -0
  285. package/dist/src/sim/vec3.d.ts +14 -0
  286. package/dist/src/sim/vec3.js +31 -0
  287. package/dist/src/sim/weapon_dynamics.d.ts +102 -0
  288. package/dist/src/sim/weapon_dynamics.js +142 -0
  289. package/dist/src/sim/weather.d.ts +95 -0
  290. package/dist/src/sim/weather.js +105 -0
  291. package/dist/src/sim/world.d.ts +52 -0
  292. package/dist/src/sim/world.js +1 -0
  293. package/dist/src/sim/wound-aging.d.ts +120 -0
  294. package/dist/src/sim/wound-aging.js +223 -0
  295. package/dist/src/species.d.ts +106 -0
  296. package/dist/src/species.js +664 -0
  297. package/dist/src/story-arcs.d.ts +17 -0
  298. package/dist/src/story-arcs.js +276 -0
  299. package/dist/src/tech-diffusion.d.ts +80 -0
  300. package/dist/src/tech-diffusion.js +185 -0
  301. package/dist/src/traits.d.ts +25 -0
  302. package/dist/src/traits.js +178 -0
  303. package/dist/src/types.d.ts +117 -0
  304. package/dist/src/types.js +1 -0
  305. package/dist/src/units.d.ts +41 -0
  306. package/dist/src/units.js +64 -0
  307. package/dist/src/weapons.d.ts +20 -0
  308. package/dist/src/weapons.js +824 -0
  309. package/dist/src/world-generation.d.ts +52 -0
  310. package/dist/src/world-generation.js +301 -0
  311. package/package.json +74 -0
@@ -0,0 +1,135 @@
1
+ import type { Q } from "../units.js";
2
+ import type { Vec3 } from "./vec3.js";
3
+ import { DamageChannel } from "../channels.js";
4
+ import type { MedicalTier } from "./medical.js";
5
+ import type { ActiveSubstance } from "./substance.js";
6
+ import type { TechCapability } from "./tech.js";
7
+ import type { WeaponDamageProfile } from "../equipment.js";
8
+ /**
9
+ * Pluggable energy-replenishment model for a CapabilitySource.
10
+ * The engine sees only the resulting reserve_J delta — source flavor is in the tags.
11
+ */
12
+ export type RegenModel = {
13
+ type: "rest";
14
+ regenRate_W: number;
15
+ } | {
16
+ type: "constant";
17
+ regenRate_W: number;
18
+ } | {
19
+ type: "ambient";
20
+ maxRate_W: number;
21
+ } | {
22
+ type: "event";
23
+ triggers: RegenTrigger[];
24
+ } | {
25
+ type: "boundless";
26
+ };
27
+ export type RegenTrigger = {
28
+ on: "kill";
29
+ amount_J: number;
30
+ } | {
31
+ on: "tick";
32
+ every_n: number;
33
+ amount_J: number;
34
+ _nextTick?: number;
35
+ } | {
36
+ on: "terrain";
37
+ tag: string;
38
+ amount_J: number;
39
+ };
40
+ /** Specification for a capability impact — maps to a DamageChannel. */
41
+ export interface ImpactSpec {
42
+ energy_J: number;
43
+ channel: DamageChannel;
44
+ }
45
+ /** Field effect placed in the world (suppression zone, environmental modifier). */
46
+ export interface FieldEffectSpec {
47
+ radius_m: number;
48
+ suppressesTags: string[];
49
+ duration_ticks: number;
50
+ /**
51
+ * Phase 12B effect chain: payload applied to every living entity inside the
52
+ * field radius each tick. Fires in the same tick the field is active,
53
+ * before expiry. The placing entity is the actor for attribution.
54
+ */
55
+ chainPayload?: EffectPayload | EffectPayload[];
56
+ }
57
+ /** A FieldEffect living in WorldState.activeFieldEffects. */
58
+ export interface FieldEffect extends FieldEffectSpec {
59
+ id: string;
60
+ origin: Vec3;
61
+ placedByEntityId: number;
62
+ }
63
+ /**
64
+ * All effect variants. Each maps to an existing engine primitive so the
65
+ * engine applies the same code path regardless of whether the effect is
66
+ * "magical" or "technological".
67
+ */
68
+ export type EffectPayload = {
69
+ kind: "impact";
70
+ spec: ImpactSpec;
71
+ } | {
72
+ kind: "treatment";
73
+ tier: MedicalTier;
74
+ rateMul: Q;
75
+ } | {
76
+ kind: "armourLayer";
77
+ resist_J: number;
78
+ channels: DamageChannel[];
79
+ duration_ticks: number;
80
+ } | {
81
+ kind: "velocity";
82
+ delta_mps: Vec3;
83
+ } | {
84
+ kind: "substance";
85
+ substance: ActiveSubstance;
86
+ } | {
87
+ kind: "structuralRepair";
88
+ region: string;
89
+ amount: Q;
90
+ } | {
91
+ kind: "fieldEffect";
92
+ spec: FieldEffectSpec;
93
+ } | {
94
+ kind: "weaponImpact";
95
+ profile: WeaponDamageProfile;
96
+ energy_J: number;
97
+ };
98
+ export interface CapabilityEffect {
99
+ id: string;
100
+ cost_J: number;
101
+ castTime_ticks: number;
102
+ cooldown_ticks?: number;
103
+ requiredCapability?: TechCapability;
104
+ range_m?: number;
105
+ aoeRadius_m?: number;
106
+ coneHalfAngle_rad?: number;
107
+ coneDir?: "facing" | "fixed";
108
+ coneDirFixed?: {
109
+ dx: number;
110
+ dy: number;
111
+ };
112
+ sustainedTicks?: number;
113
+ payload: EffectPayload | EffectPayload[];
114
+ tags?: string[];
115
+ }
116
+ export interface CapabilitySource {
117
+ id: string;
118
+ label: string;
119
+ tags: string[];
120
+ reserve_J: number;
121
+ maxReserve_J: number;
122
+ regenModel: RegenModel;
123
+ effects: CapabilityEffect[];
124
+ /**
125
+ * Phase 12B: if primary reserve is exhausted, draw activation cost from this source instead.
126
+ * Must be the `id` of another CapabilitySource on the same entity.
127
+ */
128
+ linkedFallbackId?: string;
129
+ }
130
+ export interface PendingActivation {
131
+ sourceId: string;
132
+ effectId: string;
133
+ targetId?: number;
134
+ resolveAtTick: number;
135
+ }
@@ -0,0 +1,8 @@
1
+ // src/sim/capability.ts
2
+ //
3
+ // Phase 12 — Capability Sources and Effects
4
+ //
5
+ // Implements Clarke's Third Law: "Any sufficiently advanced technology is
6
+ // indistinguishable from magic." Magic and technology are the same abstraction;
7
+ // only the tags differ. The engine cannot tell a fireball from a plasma grenade.
8
+ export {};
@@ -0,0 +1,21 @@
1
+ import { type Q } from "../units.js";
2
+ import type { Entity } from "./entity.js";
3
+ import { type Weapon, type Shield } from "../equipment.js";
4
+ import { type HitArea } from "./kinds.js";
5
+ import { BodySegment } from "./bodyplan.js";
6
+ export type { HitArea };
7
+ export interface HitResolution {
8
+ hit: boolean;
9
+ area: HitArea;
10
+ hitQuality: Q;
11
+ blocked: boolean;
12
+ parried: boolean;
13
+ shieldBlocked: boolean;
14
+ }
15
+ export declare function parryLeverageQ(wpn: Weapon, attacker: Entity): Q;
16
+ export declare function chooseArea(r01: Q): HitArea;
17
+ export declare function resolveHit(seedU32: number, attackSkill: Q, defenceSkill: Q, geometryDotQ: Q, defenceMode: "none" | "block" | "parry" | "dodge", defenceIntensity: Q): HitResolution;
18
+ /** Returns true if `shield` covers `area`. Accepts the shield item so that
19
+ * future item variants (buckler, kite, tower) can override coverage by
20
+ * checking item tags rather than hard-coding areas here. */
21
+ export declare function shieldCovers(shield: Shield, area: HitArea | BodySegment | undefined): boolean;
@@ -0,0 +1,77 @@
1
+ import { SCALE, q, qMul, clampQ, mulDiv } from "../units.js";
2
+ import { makeRng } from "../rng.js";
3
+ function weaponMomentArm_m(wpn, attacker) {
4
+ const reach = wpn.reach_m ?? Math.trunc(attacker.attributes.morphology.stature_m * 0.45);
5
+ return wpn.momentArm_m ?? Math.trunc(reach * 0.55);
6
+ }
7
+ export function parryLeverageQ(wpn, attacker) {
8
+ const arm = weaponMomentArm_m(wpn, attacker);
9
+ // reference ~0.6m human sword lever
10
+ const ref = Math.trunc(0.6 * SCALE.m);
11
+ // Clamp the raw ratio so extreme weapons stay in a sane band.
12
+ // ratio ∈ [0.5, 1.8] → formula ∈ [0.85, 1.24] → final clamp ∈ [0.85, 1.20].
13
+ // Note: the lower bound of q(0.85) is derived from the formula minimum
14
+ // (q(0.70) + qMul(q(0.5), q(0.30)) = 0.85), so it is intentionally tighter
15
+ // than the old q(0.80) which was unreachable.
16
+ const ratio = clampQ(mulDiv(arm * SCALE.Q, 1, ref), q(0.5), q(1.8));
17
+ // compress into sane band
18
+ return clampQ(q(0.70) + qMul(ratio, q(0.30)), q(0.85), // minimum reachable value given ratio ≥ 0.5
19
+ q(1.20));
20
+ }
21
+ export function chooseArea(r01) {
22
+ if (r01 < q(0.12))
23
+ return "head";
24
+ if (r01 < q(0.62))
25
+ return "torso";
26
+ if (r01 < q(0.82))
27
+ return "arm";
28
+ return "leg";
29
+ }
30
+ export function resolveHit(seedU32, attackSkill, defenceSkill, geometryDotQ, defenceMode, defenceIntensity) {
31
+ const rng = makeRng(seedU32, SCALE.Q);
32
+ const geom = clampQ(q(1.05) - mulDiv(geometryDotQ, q(0.10), SCALE.Q), q(0.85), q(1.20));
33
+ const atk = qMul(attackSkill, geom);
34
+ const diff = (atk - defenceSkill);
35
+ const p = clampQ(q(0.55) + mulDiv(diff, q(0.35), SCALE.Q), q(0.10), q(0.95));
36
+ const roll = rng.q01();
37
+ const hit = roll < p;
38
+ const area = chooseArea(rng.q01());
39
+ // Quality measures how cleanly the attack landed. It is only meaningful
40
+ // when hit === true; set to 0 on a miss so callers can't accidentally use it.
41
+ const quality = hit
42
+ ? clampQ(qMul(atk, q(0.60) + mulDiv((p - roll), q(0.40), SCALE.Q)), q(0.05), q(0.99))
43
+ : q(0);
44
+ let blocked = false;
45
+ let parried = false;
46
+ if (hit && defenceMode !== "none" && defenceIntensity > 0) {
47
+ const d = qMul(defenceIntensity, defenceSkill);
48
+ if (defenceMode === "block") {
49
+ const pb = clampQ(q(0.10) + qMul(d, q(0.60)), q(0.05), q(0.85));
50
+ blocked = rng.q01() < pb;
51
+ }
52
+ else if (defenceMode === "parry") {
53
+ const pp = clampQ(q(0.08) + qMul(d, q(0.55)), q(0.03), q(0.75));
54
+ parried = rng.q01() < pp;
55
+ }
56
+ else if (defenceMode === "dodge") {
57
+ const pd = clampQ(qMul(d, q(0.65)), q(0.05), q(0.80));
58
+ if (rng.q01() < pd)
59
+ return { hit: false, area, hitQuality: quality, blocked: false, parried: false, shieldBlocked: false };
60
+ }
61
+ }
62
+ return { hit, area, hitQuality: quality, blocked, parried, shieldBlocked: false };
63
+ }
64
+ // function isShield(item: Item): item is Shield {
65
+ // // cheap “A” that makes “B” easy later
66
+ // return (item)?.kind === "shield";
67
+ // }
68
+ /** Returns true if `shield` covers `area`. Accepts the shield item so that
69
+ * future item variants (buckler, kite, tower) can override coverage by
70
+ * checking item tags rather than hard-coding areas here. */
71
+ export function shieldCovers(shield, area) {
72
+ if (area === undefined)
73
+ return false; // no hit area = no shield coverage
74
+ // Explicit coverage list; extend when adding shield variants.
75
+ const covered = shield.covers ?? ["torso", "head"];
76
+ return covered.includes(area);
77
+ }
@@ -0,0 +1,11 @@
1
+ import type { AttackCommand, DefendCommand } from "./commands.js";
2
+ import { type Q } from "../units.js";
3
+ export declare function makeAttackCommand(targetId: number, opts?: {
4
+ weaponId?: string;
5
+ intensity?: Q;
6
+ mode?: "strike";
7
+ }): AttackCommand;
8
+ export declare function defendNone(): DefendCommand;
9
+ export declare function defendBlock(intensity?: Q): DefendCommand;
10
+ export declare function defendParry(intensity?: Q): DefendCommand;
11
+ export declare function defendDodge(intensity?: Q): DefendCommand;
@@ -0,0 +1,39 @@
1
+ import { q } from "../units.js";
2
+ export function makeAttackCommand(targetId, opts = {}) {
3
+ return {
4
+ kind: "attack",
5
+ mode: "strike",
6
+ targetId,
7
+ ...(opts.weaponId !== undefined ? { weaponId: opts.weaponId } : {}),
8
+ ...(opts.intensity !== undefined ? { intensity: opts.intensity } : {}),
9
+ ...(opts.mode !== undefined ? { mode: opts.mode } : {}),
10
+ };
11
+ }
12
+ export function defendNone() {
13
+ return {
14
+ kind: "defend",
15
+ mode: "none",
16
+ intensity: q(0),
17
+ };
18
+ }
19
+ export function defendBlock(intensity = q(1.0)) {
20
+ return {
21
+ kind: "defend",
22
+ mode: "block",
23
+ intensity,
24
+ };
25
+ }
26
+ export function defendParry(intensity = q(1.0)) {
27
+ return {
28
+ kind: "defend",
29
+ mode: "parry",
30
+ intensity,
31
+ };
32
+ }
33
+ export function defendDodge(intensity = q(1.0)) {
34
+ return {
35
+ kind: "defend",
36
+ mode: "dodge",
37
+ intensity,
38
+ };
39
+ }
@@ -0,0 +1,71 @@
1
+ import type { Q } from "../units.js";
2
+ import type { Vec3 } from "./vec3.js";
3
+ import { CommandKinds, DefenceMode, EngageModes, MoveMode } from "./kinds.js";
4
+ import type { MedicalAction, MedicalTier } from "./medical.js";
5
+ export type Command = MoveCommand | SetProneCommand | DefendCommand | AttackCommand | AttackNearestCommand | GrappleCommand | BreakGrappleCommand | BreakBindCommand | ShootCommand | TreatCommand | ActivateCommand;
6
+ export interface MoveCommand {
7
+ kind: typeof CommandKinds.Move;
8
+ dir: Vec3;
9
+ intensity: Q;
10
+ mode: MoveMode;
11
+ }
12
+ export interface SetProneCommand {
13
+ kind: typeof CommandKinds.SetProne;
14
+ prone: boolean;
15
+ }
16
+ export interface DefendCommand {
17
+ kind: typeof CommandKinds.Defend;
18
+ mode: DefenceMode;
19
+ intensity: Q;
20
+ }
21
+ export interface AttackCommand {
22
+ kind: typeof CommandKinds.Attack;
23
+ targetId: number;
24
+ weaponId?: string;
25
+ intensity?: Q;
26
+ mode?: typeof EngageModes.Strike;
27
+ }
28
+ export declare const noMove: () => MoveCommand;
29
+ export interface AttackNearestCommand {
30
+ kind: typeof CommandKinds.AttackNearest;
31
+ weaponId?: string;
32
+ intensity?: Q;
33
+ mode: typeof EngageModes.Strike;
34
+ }
35
+ export type GrappleMode = "grapple" | "throw" | "choke" | "jointLock";
36
+ export interface GrappleCommand {
37
+ kind: typeof CommandKinds.Grapple;
38
+ targetId: number;
39
+ intensity: Q;
40
+ mode?: GrappleMode;
41
+ }
42
+ export interface BreakGrappleCommand {
43
+ kind: typeof CommandKinds.BreakGrapple;
44
+ intensity: Q;
45
+ }
46
+ export interface BreakBindCommand {
47
+ kind: typeof CommandKinds.BreakBind;
48
+ intensity: Q;
49
+ }
50
+ export interface ShootCommand {
51
+ kind: typeof CommandKinds.Shoot;
52
+ targetId: number;
53
+ weaponId?: string;
54
+ intensity?: Q;
55
+ ammoId?: string;
56
+ }
57
+ export interface TreatCommand {
58
+ kind: typeof CommandKinds.Treat;
59
+ targetId: number;
60
+ action: MedicalAction;
61
+ tier: MedicalTier;
62
+ /** Region to treat. Required for tourniquet/bandage/surgery; omit for fluidReplacement. */
63
+ regionId?: string;
64
+ }
65
+ export interface ActivateCommand {
66
+ kind: typeof CommandKinds.Activate;
67
+ sourceId: string;
68
+ effectId: string;
69
+ targetId?: number;
70
+ }
71
+ export type CommandMap = Map<number, readonly Command[]>;
@@ -0,0 +1,8 @@
1
+ import { q } from "../units.js";
2
+ import { CommandKinds, MoveModes } from "./kinds.js";
3
+ export const noMove = () => ({
4
+ kind: CommandKinds.Move,
5
+ dir: { x: 0, y: 0, z: 0 },
6
+ intensity: q(0),
7
+ mode: MoveModes.Walk,
8
+ });
@@ -0,0 +1,35 @@
1
+ import { type Q } from "../units.js";
2
+ /** Phase 30: staged hunger/starvation state derived from caloricBalance_J. */
3
+ export type HungerState = "sated" | "hungry" | "starving" | "critical";
4
+ export interface ConditionState {
5
+ onFire: Q;
6
+ corrosiveExposure: Q;
7
+ radiation: Q;
8
+ electricalOverload: Q;
9
+ suffocation: Q;
10
+ stunned: Q;
11
+ prone: boolean;
12
+ pinned: boolean;
13
+ standBlockedTicks: number;
14
+ unconsciousTicks: number;
15
+ suppressedTicks: number;
16
+ blindTicks: number;
17
+ fearQ?: Q;
18
+ suppressionFearMul: Q;
19
+ recentAllyDeaths: number;
20
+ lastAllyDeathTick: number;
21
+ surrendered: boolean;
22
+ rallyCooldownTicks: number;
23
+ shieldReserve_J?: number;
24
+ shieldExpiry_tick?: number;
25
+ coreTemp_Q?: Q;
26
+ /** Caloric surplus / deficit in joules; starts at 0, goes negative as deficit grows. */
27
+ caloricBalance_J?: number;
28
+ /** Hydration surplus / deficit in hydration_J units; negative = dehydrated. */
29
+ hydrationBalance_J?: number;
30
+ /** World tick of last food or water consumption. */
31
+ lastMealTick?: number;
32
+ /** Derived from caloricBalance_J; updated by stepNutrition / consumeFood. */
33
+ hungerState?: HungerState;
34
+ }
35
+ export declare const defaultCondition: () => ConditionState;
@@ -0,0 +1,21 @@
1
+ import { q, SCALE } from "../units.js";
2
+ export const defaultCondition = () => ({
3
+ onFire: q(0),
4
+ corrosiveExposure: q(0),
5
+ radiation: q(0),
6
+ electricalOverload: q(0),
7
+ suffocation: q(0),
8
+ stunned: q(0),
9
+ prone: false,
10
+ pinned: false,
11
+ standBlockedTicks: 0,
12
+ unconsciousTicks: 0,
13
+ suppressedTicks: 0,
14
+ blindTicks: 0,
15
+ fearQ: q(0),
16
+ suppressionFearMul: SCALE.Q,
17
+ recentAllyDeaths: 0,
18
+ lastAllyDeathTick: -1,
19
+ surrendered: false,
20
+ rallyCooldownTicks: 0,
21
+ });
@@ -0,0 +1,40 @@
1
+ import type { Entity } from "./entity.js";
2
+ /**
3
+ * A directional cone defined in 2D (x-y plane).
4
+ *
5
+ * `dir` is a unit vector with magnitude SCALE.m (= 10000).
6
+ * - Facing +x at 0°: { dx: 10000, dy: 0 }
7
+ * - Facing +y at 90°: { dx: 0, dy: 10000 }
8
+ *
9
+ * `halfAngle_rad` is a config constant (outside fixed-point domain).
10
+ * `range_m` and `origin` use SCALE.m (fixed-point metres).
11
+ */
12
+ export interface ConeSpec {
13
+ origin: {
14
+ x: number;
15
+ y: number;
16
+ };
17
+ dir: {
18
+ dx: number;
19
+ dy: number;
20
+ };
21
+ halfAngle_rad: number;
22
+ range_m: number;
23
+ }
24
+ /**
25
+ * Returns true if the entity's centre is inside the cone.
26
+ *
27
+ * Geometric derivation:
28
+ * Let vec = entity.pos - cone.origin (SCALE.m units)
29
+ * dot = vec · dir = |vec| * SCALE.m * cos(θ)
30
+ * Entity is in cone iff cos(θ) ≥ cos(halfAngle_rad)
31
+ * ↔ dot ≥ cos(halfAngle_rad) * |vec| * SCALE.m
32
+ *
33
+ * Integer dot product; float threshold (halfAngle is a config constant).
34
+ */
35
+ export declare function entityInCone(entity: Entity, cone: ConeSpec): boolean;
36
+ /**
37
+ * Build a ConeSpec centred on actor using its current facingDirQ.
38
+ * facingDirQ is SCALE.Q-normalised; we rescale to SCALE.m for geometry.
39
+ */
40
+ export declare function buildEntityFacingCone(actor: Entity, halfAngle_rad: number, range_m: number): ConeSpec;
@@ -0,0 +1,44 @@
1
+ // src/sim/cone.ts — Phase 28: Cone geometry for directional AoE effects
2
+ //
3
+ // A cone is a directional AoE shape: origin, facing direction, half-angle, and range.
4
+ // Used for breath weapons, flamethrowers, sonic disorientation blasts, gas dispersal.
5
+ import { SCALE } from "../units.js";
6
+ /**
7
+ * Returns true if the entity's centre is inside the cone.
8
+ *
9
+ * Geometric derivation:
10
+ * Let vec = entity.pos - cone.origin (SCALE.m units)
11
+ * dot = vec · dir = |vec| * SCALE.m * cos(θ)
12
+ * Entity is in cone iff cos(θ) ≥ cos(halfAngle_rad)
13
+ * ↔ dot ≥ cos(halfAngle_rad) * |vec| * SCALE.m
14
+ *
15
+ * Integer dot product; float threshold (halfAngle is a config constant).
16
+ */
17
+ export function entityInCone(entity, cone) {
18
+ const ex = entity.position_m.x - cone.origin.x;
19
+ const ey = entity.position_m.y - cone.origin.y;
20
+ const distSq = ex * ex + ey * ey;
21
+ if (distSq > cone.range_m * cone.range_m)
22
+ return false;
23
+ if (distSq === 0)
24
+ return true; // at origin — inside by convention
25
+ const dist = Math.sqrt(distSq); // SCALE.m units (float OK — used in threshold comparison)
26
+ const dot = ex * cone.dir.dx + ey * cone.dir.dy;
27
+ return dot >= Math.cos(cone.halfAngle_rad) * dist * SCALE.m;
28
+ }
29
+ /**
30
+ * Build a ConeSpec centred on actor using its current facingDirQ.
31
+ * facingDirQ is SCALE.Q-normalised; we rescale to SCALE.m for geometry.
32
+ */
33
+ export function buildEntityFacingCone(actor, halfAngle_rad, range_m) {
34
+ const fx = actor.action.facingDirQ.x;
35
+ const fy = actor.action.facingDirQ.y;
36
+ const mag = Math.sqrt(fx * fx + fy * fy);
37
+ const scale = mag > 0 ? SCALE.m / mag : 1;
38
+ return {
39
+ origin: { x: actor.position_m.x, y: actor.position_m.y },
40
+ dir: { dx: Math.round(fx * scale), dy: Math.round(fy * scale) },
41
+ halfAngle_rad,
42
+ range_m,
43
+ };
44
+ }
@@ -0,0 +1,68 @@
1
+ import { SimulationTuning } from "./tuning.js";
2
+ import type { TraceSink } from "./trace.js";
3
+ import type { TerrainGrid } from "./terrain.js";
4
+ import type { DensityField } from "./density.js";
5
+ import type { SensoryEnvironment } from "./sensory.js";
6
+ import type { ObstacleGrid, ElevationGrid, SlopeGrid, HazardGrid } from "./terrain.js";
7
+ import type { TechContext } from "./tech.js";
8
+ import type { WeatherState } from "./weather.js";
9
+ import type { Q, I32 } from "../units.js";
10
+ export interface KernelContext {
11
+ tractionCoeff: Q;
12
+ tuning?: SimulationTuning;
13
+ cellSize_m?: I32;
14
+ density?: DensityField;
15
+ trace?: TraceSink;
16
+ /** Phase 4: ambient sensory conditions. Defaults to DEFAULT_SENSORY_ENV (full daylight, clear). */
17
+ sensoryEnv?: SensoryEnvironment;
18
+ /** Phase 6: per-cell terrain grid. When provided, traction is looked up by entity position. */
19
+ terrainGrid?: TerrainGrid;
20
+ /** Phase 6: impassable and partial-cover cells. q(1.0) = fully impassable; q(0.5) = 50% cover. */
21
+ obstacleGrid?: ObstacleGrid;
22
+ /** Phase 6: height above ground level per cell (SCALE.m units). Affects melee reach and projectile range. */
23
+ elevationGrid?: ElevationGrid;
24
+ /** Phase 6: per-cell slope direction and grade. Modifies effective sprint speed. */
25
+ slopeGrid?: SlopeGrid;
26
+ /** Phase 6: dynamic hazard cells (fire, radiation, poison_gas). Damage applied per tick. */
27
+ hazardGrid?: HazardGrid;
28
+ /**
29
+ * Phase 10: ambient temperature (Q 0..1).
30
+ * Comfort range: [q(0.35), q(0.65)].
31
+ * Above q(0.65) → heat stress (shock + surface damage); below q(0.35) → cold stress (shock + fatigue).
32
+ * Entity attributes `heatTolerance` and `coldTolerance` scale the dose.
33
+ */
34
+ ambientTemperature_Q?: Q;
35
+ /**
36
+ * Phase 11: technology context.
37
+ * When provided, gates which items are available.
38
+ * Does not directly affect simulation physics — use validateLoadout() before stepWorld
39
+ * to verify that the entity's loadout is era-appropriate.
40
+ */
41
+ techCtx?: TechContext;
42
+ /**
43
+ * Phase 12: ambient energy grid.
44
+ * Maps terrain cell keys to ambient energy fraction (Q, 0..1).
45
+ * Used by CapabilitySource regenModel "ambient" — regen rate scales with cell value.
46
+ * Ley lines, geothermal vents, solar collectors, stellar wind.
47
+ */
48
+ ambientGrid?: Map<string, Q>;
49
+ /**
50
+ * Phase 12B: terrain tag grid.
51
+ * Maps cell keys to arrays of string tags; used by CapabilitySource "event" regenModel
52
+ * { on: "terrain"; tag: string } triggers — fires once per cell-boundary crossing.
53
+ */
54
+ terrainTagGrid?: Map<string, string[]>;
55
+ /**
56
+ * Phase 29: ambient temperature in the Phase 29 Q encoding.
57
+ * q(0.5) = 37°C (comfortable); cToQ(0) ≈ -1852 (0°C); cToQ(30) ≈ 3704 (30°C).
58
+ * When absent, stepCoreTemp is not called and core temperature is not updated.
59
+ */
60
+ thermalAmbient_Q?: Q;
61
+ /**
62
+ * Phase 51: current weather conditions.
63
+ * When present, deriveWeatherModifiers() applies per-tick modifiers to
64
+ * tractionCoeff, sensoryEnv, thermalAmbient_Q, and ranged aim error.
65
+ * When absent, weather has no effect (backward-compatible).
66
+ */
67
+ weather?: WeatherState;
68
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { WorldState } from "./world.js";
2
+ import type { SpatialIndex } from "./spatial.js";
3
+ import type { WorldIndex } from "./indexing.js";
4
+ import type { Q } from "../units.js";
5
+ /** Per-entity crowding metrics (0..1 Q). */
6
+ export interface DensityField {
7
+ crowdingQ: Map<number, Q>;
8
+ }
9
+ export interface DensityTuning {
10
+ personalRadius_m: number;
11
+ maxNeighbours: number;
12
+ crowdingAt: number;
13
+ }
14
+ export declare function computeDensityField(world: WorldState, index: WorldIndex, spatial: SpatialIndex, t: DensityTuning): DensityField;
@@ -0,0 +1,33 @@
1
+ import { queryNearbyIds } from "./spatial.js";
2
+ import { SCALE, clampQ } from "../units.js";
3
+ export function computeDensityField(world, index, spatial, t) {
4
+ const crowdingQ = new Map();
5
+ const R = t.personalRadius_m;
6
+ for (const e of world.entities) {
7
+ if (e.injury.dead)
8
+ continue;
9
+ const ids = queryNearbyIds(spatial, e.position_m, R);
10
+ ids.sort((a, b) => a - b);
11
+ let n = 0;
12
+ for (const id of ids) {
13
+ if (id === e.id)
14
+ continue;
15
+ const o = index.byId.get(id);
16
+ if (!o || o.injury.dead)
17
+ continue;
18
+ // count only within true radius (avoid square query overcount)
19
+ const dx = o.position_m.x - e.position_m.x;
20
+ const dy = o.position_m.y - e.position_m.y;
21
+ const dz = o.position_m.z - e.position_m.z;
22
+ const d2 = BigInt(dx) * BigInt(dx) + BigInt(dy) * BigInt(dy) + BigInt(dz) * BigInt(dz);
23
+ if (d2 <= BigInt(R) * BigInt(R))
24
+ n++;
25
+ if (n >= t.maxNeighbours)
26
+ break;
27
+ }
28
+ // map neighbour count to 0..1 Q
29
+ const qv = clampQ(Math.trunc((n * SCALE.Q) / Math.max(1, t.crowdingAt)), 0, SCALE.Q);
30
+ crowdingQ.set(e.id, qv);
31
+ }
32
+ return { crowdingQ };
33
+ }