@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,52 @@
1
+ import type { Q } from "./units.js";
2
+ import type { Settlement } from "./settlement.js";
3
+ import type { Faction, FactionRegistry } from "./faction.js";
4
+ import type { RelationshipGraph } from "./relationships.js";
5
+ import type { ChronicleRegistry } from "./chronicle.js";
6
+ import type { SpeciesEntitySpec } from "./species.js";
7
+ export interface WorldGenConfig {
8
+ /** World seed for deterministic generation */
9
+ worldSeed: number;
10
+ /** Number of settlements to generate */
11
+ settlementCount: number;
12
+ /** Number of factions to generate */
13
+ factionCount: number;
14
+ /** Average entities per settlement */
15
+ entitiesPerSettlement: number;
16
+ /** World bounds in meters */
17
+ worldSize_m: number;
18
+ /** Era/tech level for generation */
19
+ era: "ancient" | "medieval" | "renaissance" | "industrial" | "modern" | "future";
20
+ /** Enable starting conflicts between factions */
21
+ enableStartingConflicts: boolean;
22
+ /** Density of pre-existing relationships (0-1) */
23
+ relationshipDensity: Q;
24
+ }
25
+ export declare const DEFAULT_WORLDGEN_CONFIG: WorldGenConfig;
26
+ export interface WorldInhabitant {
27
+ entityId: number;
28
+ teamId?: string;
29
+ settlementId: string;
30
+ spec: SpeciesEntitySpec;
31
+ name: string;
32
+ }
33
+ export interface GeneratedWorld {
34
+ worldSeed: number;
35
+ config: WorldGenConfig;
36
+ settlements: Settlement[];
37
+ factions: Faction[];
38
+ factionRegistry: FactionRegistry;
39
+ inhabitants: WorldInhabitant[];
40
+ settlementInhabitants: Map<string, number[]>;
41
+ factionMembers: Map<string, number[]>;
42
+ relationshipGraph: RelationshipGraph;
43
+ chronicleRegistry: ChronicleRegistry;
44
+ createdAtTick: number;
45
+ }
46
+ export declare function generateWorld(config?: WorldGenConfig, tick?: number): GeneratedWorld;
47
+ export declare function getWorldSummary(world: GeneratedWorld): {
48
+ totalInhabitants: number;
49
+ totalRelationships: number;
50
+ settlementSummary: string[];
51
+ factionSummary: string[];
52
+ };
@@ -0,0 +1,301 @@
1
+ // src/world-generation.ts — Phase 46: Procedural World Generation
2
+ //
3
+ // Deterministic generation of settlements, factions, and starting relationships
4
+ // from a single world seed. Integrates with settlement (Phase 44), faction
5
+ // (Phase 39), relationships (Phase 42), and chronicle (Phase 45) systems.
6
+ import { q, SCALE } from "./units.js";
7
+ import { makeRng } from "./rng.js";
8
+ import { eventSeed } from "./sim/seeds.js";
9
+ import { createSettlement, SETTLEMENT_TIER_NAMES } from "./settlement.js";
10
+ import { createFactionRegistry, STANDING_NEUTRAL } from "./faction.js";
11
+ import { establishRelationship } from "./relationships.js";
12
+ import { createChronicleRegistry, addChronicleEntry } from "./chronicle.js";
13
+ import { generateSpeciesIndividual, FANTASY_HUMANOID_SPECIES } from "./species.js";
14
+ export const DEFAULT_WORLDGEN_CONFIG = {
15
+ worldSeed: 12345,
16
+ settlementCount: 5,
17
+ factionCount: 3,
18
+ entitiesPerSettlement: 10,
19
+ worldSize_m: 10000,
20
+ era: "medieval",
21
+ enableStartingConflicts: true,
22
+ relationshipDensity: q(0.3),
23
+ };
24
+ // ── Name Generators ───────────────────────────────────────────────────────────
25
+ const SETTLEMENT_PREFIXES = [
26
+ "North", "South", "East", "West", "High", "Low", "Deep", "Bright", "Shadow",
27
+ "Stone", "Iron", "Gold", "Silver", "Oak", "Pine", "River", "Lake", "Frost",
28
+ "Ember", "Dusk", "Dawn", "Storm", "Wind", "Thorn", "Ash", "Mist",
29
+ ];
30
+ const SETTLEMENT_SUFFIXES = [
31
+ "haven", "ford", "burg", "heim", "ton", "ville", "port", "stead",
32
+ "wich", "by", "minster", "borough", "ham", "field", "crest", "fall",
33
+ "watch", "keep", "spire", "glen", "moor", "holm", "strand",
34
+ ];
35
+ const FACTION_ADJECTIVES = [
36
+ "Iron", "Golden", "Crimson", "Azure", "Shadow", "Radiant", "Silent",
37
+ "Valiant", "Mercantile", "Ancient", "Noble", "Common", "Sovereign",
38
+ "Mystic", "Stalwart", "Wandering", "Bold", "Cunning", "Honorable",
39
+ ];
40
+ const FACTION_NOUNS = [
41
+ "Legion", "Guild", "Order", "League", "Covenant", "Compact", "Alliance",
42
+ "Company", "Clan", "House", "Crown", "Council", "Circle", "Brotherhood",
43
+ "Sisterhood", "Fellowship", "Union", "Coalition", "Society", "Congregation",
44
+ ];
45
+ const FIRST_NAMES = [
46
+ "Aldric", "Beorn", "Cedric", "Duncan", "Eadric", "Faramond", "Godric", "Harold",
47
+ "Ivor", "Jareth", "Kendrick", "Leofric", "Merrick", "Nigel", "Oswin", "Percival",
48
+ "Quentin", "Rowan", "Sigeric", "Theobald", "Ulric", "Vortigern", "Wulfric", "Yorick",
49
+ "Aeliana", "Brunhild", "Cassandra", "Daphne", "Elowen", "Freya", "Guinevere", "Hilda",
50
+ "Isolde", "Jocelyn", "Kira", "Linnea", "Morgana", "Nimue", "Ophelia", "Rowena",
51
+ ];
52
+ function randomIndex(rngQ01, arrayLength) {
53
+ return Math.floor((rngQ01 / SCALE.Q) * arrayLength);
54
+ }
55
+ function generateSettlementName(rng) {
56
+ const prefix = SETTLEMENT_PREFIXES[randomIndex(rng.q01(), SETTLEMENT_PREFIXES.length)];
57
+ const suffix = SETTLEMENT_SUFFIXES[randomIndex(rng.q01(), SETTLEMENT_SUFFIXES.length)];
58
+ return prefix + suffix;
59
+ }
60
+ function generateFactionName(rng) {
61
+ const adj = FACTION_ADJECTIVES[randomIndex(rng.q01(), FACTION_ADJECTIVES.length)];
62
+ const noun = FACTION_NOUNS[randomIndex(rng.q01(), FACTION_NOUNS.length)];
63
+ return `The ${adj} ${noun}`;
64
+ }
65
+ function generateIndividualName(rng) {
66
+ return FIRST_NAMES[randomIndex(rng.q01(), FIRST_NAMES.length)];
67
+ }
68
+ // ── Settlement Generation ─────────────────────────────────────────────────────
69
+ function generateSettlements(config, tick) {
70
+ const settlements = [];
71
+ for (let i = 0; i < config.settlementCount; i++) {
72
+ const seed = eventSeed(config.worldSeed, tick, i, 0, 0x5E771E);
73
+ const rng = makeRng(seed, SCALE.Q);
74
+ const angle = (i / config.settlementCount) * Math.PI * 2 + (rng.q01() / SCALE.Q) * 0.5;
75
+ const dist = (rng.q01() / SCALE.Q) * config.worldSize_m * 0.4;
76
+ const x = Math.trunc(config.worldSize_m / 2 + Math.cos(angle) * dist);
77
+ const y = Math.trunc(config.worldSize_m / 2 + Math.sin(angle) * dist);
78
+ const tierRoll = rng.q01() / SCALE.Q;
79
+ let tier = 0;
80
+ if (tierRoll > 0.7)
81
+ tier = 1;
82
+ if (tierRoll > 0.85)
83
+ tier = 2;
84
+ if (tierRoll > 0.95)
85
+ tier = 3;
86
+ if (tierRoll > 0.99)
87
+ tier = 4;
88
+ const name = generateSettlementName(rng);
89
+ const settlementId = `settlement_${i}`;
90
+ const settlement = createSettlement(settlementId, name, { x, y }, tick, tier);
91
+ settlements.push(settlement);
92
+ }
93
+ return settlements;
94
+ }
95
+ // ── Faction Generation ─────────────────────────────────────────────────────────
96
+ function generateFactions(config, settlements, tick) {
97
+ const factions = [];
98
+ for (let i = 0; i < config.factionCount; i++) {
99
+ const seed = eventSeed(config.worldSeed, tick, i, 0, 0xFAC710);
100
+ const localRng = makeRng(seed, SCALE.Q);
101
+ const name = generateFactionName(localRng);
102
+ const factionId = `faction_${i}`;
103
+ const faction = {
104
+ id: factionId,
105
+ name,
106
+ rivals: new Set(),
107
+ allies: new Set(),
108
+ };
109
+ factions.push(faction);
110
+ }
111
+ if (config.enableStartingConflicts) {
112
+ for (let i = 0; i < factions.length; i++) {
113
+ for (let j = i + 1; j < factions.length; j++) {
114
+ const seed = eventSeed(config.worldSeed, tick, i, j, 0xFAC7);
115
+ const relRng = makeRng(seed, SCALE.Q);
116
+ const factionA = factions[i];
117
+ const factionB = factions[j];
118
+ if (relRng.q01() / SCALE.Q < 0.3) {
119
+ factionA.rivals.add(factionB.id);
120
+ }
121
+ else if (relRng.q01() / SCALE.Q < 0.5) {
122
+ factionA.allies.add(factionB.id);
123
+ factionB.allies.add(factionA.id);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ const registry = createFactionRegistry(factions);
129
+ return { factions, registry };
130
+ }
131
+ // ── Entity Generation ─────────────────────────────────────────────────────────
132
+ function getSpeciesForEra(_era) {
133
+ return [...FANTASY_HUMANOID_SPECIES];
134
+ }
135
+ function generateInhabitants(config, settlements, factions, tick) {
136
+ const inhabitants = [];
137
+ const settlementInhabitants = new Map();
138
+ const factionMembers = new Map();
139
+ let entityIdCounter = 1;
140
+ const availableSpecies = getSpeciesForEra(config.era);
141
+ for (let settlementIdx = 0; settlementIdx < settlements.length; settlementIdx++) {
142
+ const settlement = settlements[settlementIdx];
143
+ const entityIds = [];
144
+ const rng = makeRng(eventSeed(config.worldSeed, tick, settlementIdx, 0, 0x5E7720), SCALE.Q);
145
+ const basePop = Math.max(5, Math.floor(config.entitiesPerSettlement * (0.7 + (rng.q01() / SCALE.Q) * 0.6)));
146
+ const population = Math.min(basePop, settlement.populationCap);
147
+ const settlementFaction = factions.find((_, idx) => {
148
+ const factionIndex = settlements.indexOf(settlement) % factions.length;
149
+ return idx === factionIndex;
150
+ });
151
+ for (let i = 0; i < population; i++) {
152
+ const entitySeed = eventSeed(config.worldSeed, tick, i, 0, 0x5E7721);
153
+ const species = availableSpecies[randomIndex(rng.q01(), availableSpecies.length)];
154
+ const spec = generateSpeciesIndividual(species, entitySeed);
155
+ const entityId = entityIdCounter++;
156
+ const name = generateIndividualName(makeRng(entitySeed, SCALE.Q));
157
+ const inhabitant = {
158
+ entityId,
159
+ settlementId: settlement.settlementId,
160
+ spec,
161
+ name,
162
+ };
163
+ if (settlementFaction && rng.q01() / SCALE.Q < 0.7) {
164
+ inhabitant.teamId = settlementFaction.id;
165
+ if (!factionMembers.has(settlementFaction.id)) {
166
+ factionMembers.set(settlementFaction.id, []);
167
+ }
168
+ factionMembers.get(settlementFaction.id).push(entityId);
169
+ }
170
+ inhabitants.push(inhabitant);
171
+ entityIds.push(entityId);
172
+ }
173
+ settlementInhabitants.set(settlement.settlementId, entityIds);
174
+ settlement.population = population;
175
+ }
176
+ return { inhabitants, settlementInhabitants, factionMembers };
177
+ }
178
+ // ── Relationship Generation ───────────────────────────────────────────────────
179
+ function generateRelationships(config, inhabitants, factionRegistry, tick) {
180
+ const graph = {
181
+ relationships: new Map(),
182
+ entityIndex: new Map(),
183
+ };
184
+ const rng = makeRng(eventSeed(config.worldSeed, tick, 0, 0, 0x5EED50), SCALE.Q);
185
+ for (let i = 0; i < inhabitants.length; i++) {
186
+ for (let j = i + 1; j < inhabitants.length; j++) {
187
+ const entityA = inhabitants[i];
188
+ const entityB = inhabitants[j];
189
+ if (rng.q01() > config.relationshipDensity)
190
+ continue;
191
+ const seed = eventSeed(config.worldSeed, tick, entityA.entityId, entityB.entityId, 0x5EED51);
192
+ const relRng = makeRng(seed, SCALE.Q);
193
+ let baseAffinity = q(0);
194
+ if (entityA.teamId && entityB.teamId) {
195
+ if (entityA.teamId === entityB.teamId) {
196
+ baseAffinity = q(0.4);
197
+ }
198
+ else {
199
+ const standing = factionRegistry.globalStanding.get(entityA.teamId)?.get(entityB.teamId);
200
+ if (standing !== undefined) {
201
+ baseAffinity = standing - STANDING_NEUTRAL;
202
+ }
203
+ }
204
+ }
205
+ if (entityA.settlementId === entityB.settlementId) {
206
+ baseAffinity += q(0.1);
207
+ }
208
+ const variance = Math.floor(((relRng.q01() / SCALE.Q) - 0.5) * q(0.4));
209
+ const affinity = Math.max(-SCALE.Q, Math.min(SCALE.Q, baseAffinity + variance));
210
+ const trust = Math.floor(Math.abs(affinity) * q(0.6));
211
+ if (Math.abs(affinity) > q(0.1)) {
212
+ establishRelationship(graph, entityA.entityId, entityB.entityId, tick, affinity, trust);
213
+ }
214
+ }
215
+ }
216
+ return graph;
217
+ }
218
+ // ── Chronicle Generation ───────────────────────────────────────────────────────
219
+ function generateWorldChronicles(config, settlements, factions, inhabitants, tick) {
220
+ const registry = createChronicleRegistry(tick);
221
+ addChronicleEntry(registry.worldChronicle, {
222
+ tick,
223
+ significance: 100,
224
+ eventType: "first_contact",
225
+ actors: [],
226
+ template: "world_creation",
227
+ variables: {
228
+ settlementCount: settlements.length,
229
+ factionCount: factions.length,
230
+ era: config.era,
231
+ },
232
+ });
233
+ for (const settlement of settlements) {
234
+ const founder = inhabitants.find((i) => i.settlementId === settlement.settlementId);
235
+ addChronicleEntry(registry.worldChronicle, {
236
+ tick: tick + 1,
237
+ significance: 60,
238
+ eventType: "settlement_founded",
239
+ actors: founder ? [founder.entityId] : [],
240
+ template: "settlement_founded",
241
+ variables: {
242
+ settlementName: settlement.name,
243
+ founder: founder?.name ?? "Unknown",
244
+ tier: SETTLEMENT_TIER_NAMES[settlement.tier],
245
+ },
246
+ settlementId: settlement.settlementId,
247
+ });
248
+ }
249
+ for (const faction of factions) {
250
+ addChronicleEntry(registry.worldChronicle, {
251
+ tick: tick + 2,
252
+ significance: 50,
253
+ eventType: "first_contact",
254
+ actors: [],
255
+ template: "faction_formed",
256
+ variables: {
257
+ factionName: faction.name,
258
+ homeSettlement: faction.id,
259
+ },
260
+ });
261
+ }
262
+ return registry;
263
+ }
264
+ // ── Main Generation Entry Point ────────────────────────────────────────────────
265
+ export function generateWorld(config = DEFAULT_WORLDGEN_CONFIG, tick = 0) {
266
+ const settlements = generateSettlements(config, tick);
267
+ const { factions, registry: factionRegistry } = generateFactions(config, settlements, tick);
268
+ const { inhabitants, settlementInhabitants, factionMembers } = generateInhabitants(config, settlements, factions, tick);
269
+ const relationshipGraph = generateRelationships(config, inhabitants, factionRegistry, tick);
270
+ const chronicleRegistry = generateWorldChronicles(config, settlements, factions, inhabitants, tick);
271
+ return {
272
+ worldSeed: config.worldSeed,
273
+ config,
274
+ settlements,
275
+ factions,
276
+ factionRegistry,
277
+ inhabitants,
278
+ settlementInhabitants,
279
+ factionMembers,
280
+ relationshipGraph,
281
+ chronicleRegistry,
282
+ createdAtTick: tick,
283
+ };
284
+ }
285
+ // ── World Summary ─────────────────────────────────────────────────────────────
286
+ export function getWorldSummary(world) {
287
+ const totalRelationships = world.relationshipGraph.relationships.size;
288
+ const settlementSummary = world.settlements.map((s) => `${s.name} (${SETTLEMENT_TIER_NAMES[s.tier]}): ${s.population} people`);
289
+ const factionSummary = world.factions.map((f) => {
290
+ const members = world.factionMembers.get(f.id)?.length ?? 0;
291
+ const rivals = f.rivals.size > 0 ? ` [rivals: ${[...f.rivals].join(", ")}]` : "";
292
+ const allies = f.allies.size > 0 ? ` [allies: ${[...f.allies].join(", ")}]` : "";
293
+ return `${f.name}: ${members} members${rivals}${allies}`;
294
+ });
295
+ return {
296
+ totalInhabitants: world.inhabitants.length,
297
+ totalRelationships,
298
+ settlementSummary,
299
+ factionSummary,
300
+ };
301
+ }
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@its-not-rocket-science/ananke",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Deterministic lockstep-friendly SI-units RPG/physics core (fixed-point TS)",
6
+ "license": "MIT",
7
+ "main": "./dist/src/index.js",
8
+ "types": "./dist/src/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/src/index.js",
12
+ "types": "./dist/src/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/src",
17
+ "CHANGELOG.md",
18
+ "STABLE_API.md"
19
+ ],
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/its-not-rocket-science/ananke.git"
26
+ },
27
+ "keywords": [
28
+ "simulation", "physics", "combat", "rpg",
29
+ "deterministic", "fixed-point", "game-engine"
30
+ ],
31
+ "scripts": {
32
+ "prepublishOnly": "npm run build && npm run test:coverage",
33
+ "build": "tsc -p tsconfig.build.json",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "test:coverage": "vitest run --coverage",
37
+ "ci": "npm run build && npm run test:coverage",
38
+ "lint": "node tools/lint-open.mjs",
39
+ "run:demo": "node dist/tools/run-demo.js",
40
+ "run:vertical-slice": "node dist/tools/vertical-slice.js",
41
+ "run:observer": "node dist/tools/observer.js",
42
+ "run:serialize": "node dist/tools/serialize.js",
43
+ "run:trace-attack": "node dist/tools/trace-attack.js",
44
+ "run:validation": "node dist/tools/validation.js",
45
+ "run:bridge-demo": "node dist/tools/bridge-demo.js",
46
+ "run:narrative-stress-test": "node dist/tools/narrative-stress-test.js",
47
+ "run:narrative-stress-cinema": "node dist/tools/narrative-stress-cinema.js",
48
+ "run:blade-runner": "node dist/tools/blade-runner.js",
49
+ "run:emergent-validation": "node dist/tools/emergent-validation.js",
50
+ "run:benchmark": "node dist/tools/benchmark.js",
51
+ "run:validation-dashboard": "node dist/tools/validation.js --dashboard",
52
+ "run:what-if": "node dist/tools/what-if.js",
53
+ "example:combat": "node dist/examples/quickstart-combat.js",
54
+ "example:campaign": "node dist/examples/quickstart-campaign.js",
55
+ "example:species": "node dist/examples/quickstart-species.js",
56
+ "generate-fixtures": "node dist/tools/generate-fixtures.js",
57
+ "generate-zoo": "node dist/tools/generate-zoo.js",
58
+ "generate-map": "node dist/tools/generate-map.js",
59
+ "world-server": "node dist/tools/world-server.js",
60
+ "benchmark-check": "node dist/tools/benchmark-check.js",
61
+ "benchmark-check:strict": "node dist/tools/benchmark-check.js --threshold=0.10",
62
+ "benchmark-check:update": "node dist/tools/benchmark-check.js --update-baseline",
63
+ "benchmark:guide": "node dist/tools/benchmark-guide.js"
64
+ },
65
+ "devDependencies": {
66
+ "@eslint/js": "^9.39.3",
67
+ "@types/node": "^20.0.0",
68
+ "@vitest/coverage-v8": "^2.1.8",
69
+ "eslint": "^9.39.3",
70
+ "typescript": "^5.5.4",
71
+ "typescript-eslint": "^8.56.1",
72
+ "vitest": "^2.1.8"
73
+ }
74
+ }