@alife-sdk/core 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 (367) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +283 -0
  3. package/dist/ai/DangerManager.d.ts +71 -0
  4. package/dist/ai/DangerManager.d.ts.map +1 -0
  5. package/dist/ai/DangerManager.js +176 -0
  6. package/dist/ai/DangerManager.js.map +1 -0
  7. package/dist/ai/GOAPAction.d.ts +45 -0
  8. package/dist/ai/GOAPAction.d.ts.map +1 -0
  9. package/dist/ai/GOAPAction.js +32 -0
  10. package/dist/ai/GOAPAction.js.map +1 -0
  11. package/dist/ai/GOAPPlanner.d.ts +80 -0
  12. package/dist/ai/GOAPPlanner.d.ts.map +1 -0
  13. package/dist/ai/GOAPPlanner.js +259 -0
  14. package/dist/ai/GOAPPlanner.js.map +1 -0
  15. package/dist/ai/IStateHandler.d.ts +8 -0
  16. package/dist/ai/IStateHandler.d.ts.map +1 -0
  17. package/dist/ai/IStateHandler.js +8 -0
  18. package/dist/ai/IStateHandler.js.map +1 -0
  19. package/dist/ai/MemorySystem.d.ts +94 -0
  20. package/dist/ai/MemorySystem.d.ts.map +1 -0
  21. package/dist/ai/MemorySystem.js +207 -0
  22. package/dist/ai/MemorySystem.js.map +1 -0
  23. package/dist/ai/StateMachine.d.ts +49 -0
  24. package/dist/ai/StateMachine.d.ts.map +1 -0
  25. package/dist/ai/StateMachine.js +83 -0
  26. package/dist/ai/StateMachine.js.map +1 -0
  27. package/dist/ai/WorldState.d.ts +48 -0
  28. package/dist/ai/WorldState.d.ts.map +1 -0
  29. package/dist/ai/WorldState.js +93 -0
  30. package/dist/ai/WorldState.js.map +1 -0
  31. package/dist/ai/index.d.ts +10 -0
  32. package/dist/ai/index.d.ts.map +1 -0
  33. package/dist/ai/index.js +8 -0
  34. package/dist/ai/index.js.map +1 -0
  35. package/dist/combat/DamageInstance.d.ts +26 -0
  36. package/dist/combat/DamageInstance.d.ts.map +1 -0
  37. package/dist/combat/DamageInstance.js +25 -0
  38. package/dist/combat/DamageInstance.js.map +1 -0
  39. package/dist/combat/MoraleStateMachine.d.ts +53 -0
  40. package/dist/combat/MoraleStateMachine.d.ts.map +1 -0
  41. package/dist/combat/MoraleStateMachine.js +84 -0
  42. package/dist/combat/MoraleStateMachine.js.map +1 -0
  43. package/dist/combat/index.d.ts +5 -0
  44. package/dist/combat/index.d.ts.map +1 -0
  45. package/dist/combat/index.js +3 -0
  46. package/dist/combat/index.js.map +1 -0
  47. package/dist/config/ALifeConfig.d.ts +131 -0
  48. package/dist/config/ALifeConfig.d.ts.map +1 -0
  49. package/dist/config/ALifeConfig.js +82 -0
  50. package/dist/config/ALifeConfig.js.map +1 -0
  51. package/dist/config/index.d.ts +3 -0
  52. package/dist/config/index.d.ts.map +1 -0
  53. package/dist/config/index.js +2 -0
  54. package/dist/config/index.js.map +1 -0
  55. package/dist/core/ALifeKernel.d.ts +163 -0
  56. package/dist/core/ALifeKernel.d.ts.map +1 -0
  57. package/dist/core/ALifeKernel.js +542 -0
  58. package/dist/core/ALifeKernel.js.map +1 -0
  59. package/dist/core/Clock.d.ts +123 -0
  60. package/dist/core/Clock.d.ts.map +1 -0
  61. package/dist/core/Clock.js +228 -0
  62. package/dist/core/Clock.js.map +1 -0
  63. package/dist/core/DevToolsInspector.d.ts +53 -0
  64. package/dist/core/DevToolsInspector.d.ts.map +1 -0
  65. package/dist/core/DevToolsInspector.js +8 -0
  66. package/dist/core/DevToolsInspector.js.map +1 -0
  67. package/dist/core/Diagnostics.d.ts +64 -0
  68. package/dist/core/Diagnostics.d.ts.map +1 -0
  69. package/dist/core/Diagnostics.js +107 -0
  70. package/dist/core/Diagnostics.js.map +1 -0
  71. package/dist/core/ISerializable.d.ts +12 -0
  72. package/dist/core/ISerializable.d.ts.map +1 -0
  73. package/dist/core/ISerializable.js +2 -0
  74. package/dist/core/ISerializable.js.map +1 -0
  75. package/dist/core/PortRegistry.d.ts +57 -0
  76. package/dist/core/PortRegistry.d.ts.map +1 -0
  77. package/dist/core/PortRegistry.js +72 -0
  78. package/dist/core/PortRegistry.js.map +1 -0
  79. package/dist/core/PortTokens.d.ts +39 -0
  80. package/dist/core/PortTokens.d.ts.map +1 -0
  81. package/dist/core/PortTokens.js +39 -0
  82. package/dist/core/PortTokens.js.map +1 -0
  83. package/dist/core/SpatialGrid.d.ts +114 -0
  84. package/dist/core/SpatialGrid.d.ts.map +1 -0
  85. package/dist/core/SpatialGrid.js +258 -0
  86. package/dist/core/SpatialGrid.js.map +1 -0
  87. package/dist/core/Vec2.d.ts +34 -0
  88. package/dist/core/Vec2.d.ts.map +1 -0
  89. package/dist/core/Vec2.js +52 -0
  90. package/dist/core/Vec2.js.map +1 -0
  91. package/dist/core/math/CatmullRom.d.ts +20 -0
  92. package/dist/core/math/CatmullRom.d.ts.map +1 -0
  93. package/dist/core/math/CatmullRom.js +37 -0
  94. package/dist/core/math/CatmullRom.js.map +1 -0
  95. package/dist/core/math/index.d.ts +6 -0
  96. package/dist/core/math/index.d.ts.map +1 -0
  97. package/dist/core/math/index.js +5 -0
  98. package/dist/core/math/index.js.map +1 -0
  99. package/dist/core/math/intersects.d.ts +32 -0
  100. package/dist/core/math/intersects.d.ts.map +1 -0
  101. package/dist/core/math/intersects.js +92 -0
  102. package/dist/core/math/intersects.js.map +1 -0
  103. package/dist/core/math/utils.d.ts +5 -0
  104. package/dist/core/math/utils.d.ts.map +1 -0
  105. package/dist/core/math/utils.js +13 -0
  106. package/dist/core/math/utils.js.map +1 -0
  107. package/dist/entity/IComponent.d.ts +17 -0
  108. package/dist/entity/IComponent.d.ts.map +1 -0
  109. package/dist/entity/IComponent.js +2 -0
  110. package/dist/entity/IComponent.js.map +1 -0
  111. package/dist/entity/IEntity.d.ts +33 -0
  112. package/dist/entity/IEntity.d.ts.map +1 -0
  113. package/dist/entity/IEntity.js +2 -0
  114. package/dist/entity/IEntity.js.map +1 -0
  115. package/dist/entity/index.d.ts +3 -0
  116. package/dist/entity/index.d.ts.map +1 -0
  117. package/dist/entity/index.js +2 -0
  118. package/dist/entity/index.js.map +1 -0
  119. package/dist/events/ALifeEvents.d.ts +241 -0
  120. package/dist/events/ALifeEvents.d.ts.map +1 -0
  121. package/dist/events/ALifeEvents.js +53 -0
  122. package/dist/events/ALifeEvents.js.map +1 -0
  123. package/dist/events/EventBus.d.ts +52 -0
  124. package/dist/events/EventBus.d.ts.map +1 -0
  125. package/dist/events/EventBus.js +129 -0
  126. package/dist/events/EventBus.js.map +1 -0
  127. package/dist/events/index.d.ts +4 -0
  128. package/dist/events/index.d.ts.map +1 -0
  129. package/dist/events/index.js +4 -0
  130. package/dist/events/index.js.map +1 -0
  131. package/dist/faction/Faction.d.ts +53 -0
  132. package/dist/faction/Faction.d.ts.map +1 -0
  133. package/dist/faction/Faction.js +101 -0
  134. package/dist/faction/Faction.js.map +1 -0
  135. package/dist/faction/FactionBuilder.d.ts +32 -0
  136. package/dist/faction/FactionBuilder.d.ts.map +1 -0
  137. package/dist/faction/FactionBuilder.js +80 -0
  138. package/dist/faction/FactionBuilder.js.map +1 -0
  139. package/dist/faction/ImmunityProfile.d.ts +24 -0
  140. package/dist/faction/ImmunityProfile.d.ts.map +1 -0
  141. package/dist/faction/ImmunityProfile.js +43 -0
  142. package/dist/faction/ImmunityProfile.js.map +1 -0
  143. package/dist/faction/index.d.ts +6 -0
  144. package/dist/faction/index.d.ts.map +1 -0
  145. package/dist/faction/index.js +5 -0
  146. package/dist/faction/index.js.map +1 -0
  147. package/dist/index.d.ts +32 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +34 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/logger/ILogEntry.d.ts +16 -0
  152. package/dist/logger/ILogEntry.d.ts.map +1 -0
  153. package/dist/logger/ILogEntry.js +2 -0
  154. package/dist/logger/ILogEntry.js.map +1 -0
  155. package/dist/logger/LogChannel.d.ts +27 -0
  156. package/dist/logger/LogChannel.d.ts.map +1 -0
  157. package/dist/logger/LogChannel.js +26 -0
  158. package/dist/logger/LogChannel.js.map +1 -0
  159. package/dist/logger/LogLevel.d.ts +10 -0
  160. package/dist/logger/LogLevel.d.ts.map +1 -0
  161. package/dist/logger/LogLevel.js +9 -0
  162. package/dist/logger/LogLevel.js.map +1 -0
  163. package/dist/logger/Logger.d.ts +56 -0
  164. package/dist/logger/Logger.d.ts.map +1 -0
  165. package/dist/logger/Logger.js +106 -0
  166. package/dist/logger/Logger.js.map +1 -0
  167. package/dist/logger/index.d.ts +8 -0
  168. package/dist/logger/index.d.ts.map +1 -0
  169. package/dist/logger/index.js +5 -0
  170. package/dist/logger/index.js.map +1 -0
  171. package/dist/movement/MonsterHome.d.ts +49 -0
  172. package/dist/movement/MonsterHome.d.ts.map +1 -0
  173. package/dist/movement/MonsterHome.js +75 -0
  174. package/dist/movement/MonsterHome.js.map +1 -0
  175. package/dist/movement/PatrolRoute.d.ts +99 -0
  176. package/dist/movement/PatrolRoute.d.ts.map +1 -0
  177. package/dist/movement/PatrolRoute.js +141 -0
  178. package/dist/movement/PatrolRoute.js.map +1 -0
  179. package/dist/movement/index.d.ts +5 -0
  180. package/dist/movement/index.d.ts.map +1 -0
  181. package/dist/movement/index.js +4 -0
  182. package/dist/movement/index.js.map +1 -0
  183. package/dist/navigation/LevelGraph.d.ts +78 -0
  184. package/dist/navigation/LevelGraph.d.ts.map +1 -0
  185. package/dist/navigation/LevelGraph.js +268 -0
  186. package/dist/navigation/LevelGraph.js.map +1 -0
  187. package/dist/navigation/NPCGraphMover.d.ts +87 -0
  188. package/dist/navigation/NPCGraphMover.d.ts.map +1 -0
  189. package/dist/navigation/NPCGraphMover.js +193 -0
  190. package/dist/navigation/NPCGraphMover.js.map +1 -0
  191. package/dist/navigation/index.d.ts +5 -0
  192. package/dist/navigation/index.d.ts.map +1 -0
  193. package/dist/navigation/index.js +4 -0
  194. package/dist/navigation/index.js.map +1 -0
  195. package/dist/plugins/AnomaliesPlugin.d.ts +26 -0
  196. package/dist/plugins/AnomaliesPlugin.d.ts.map +1 -0
  197. package/dist/plugins/AnomaliesPlugin.js +30 -0
  198. package/dist/plugins/AnomaliesPlugin.js.map +1 -0
  199. package/dist/plugins/CombatSchemaPlugin.d.ts +35 -0
  200. package/dist/plugins/CombatSchemaPlugin.d.ts.map +1 -0
  201. package/dist/plugins/CombatSchemaPlugin.js +44 -0
  202. package/dist/plugins/CombatSchemaPlugin.js.map +1 -0
  203. package/dist/plugins/FactionsPlugin.d.ts +26 -0
  204. package/dist/plugins/FactionsPlugin.d.ts.map +1 -0
  205. package/dist/plugins/FactionsPlugin.js +30 -0
  206. package/dist/plugins/FactionsPlugin.js.map +1 -0
  207. package/dist/plugins/IALifePlugin.d.ts +91 -0
  208. package/dist/plugins/IALifePlugin.d.ts.map +1 -0
  209. package/dist/plugins/IALifePlugin.js +2 -0
  210. package/dist/plugins/IALifePlugin.js.map +1 -0
  211. package/dist/plugins/MonstersPlugin.d.ts +26 -0
  212. package/dist/plugins/MonstersPlugin.d.ts.map +1 -0
  213. package/dist/plugins/MonstersPlugin.js +30 -0
  214. package/dist/plugins/MonstersPlugin.js.map +1 -0
  215. package/dist/plugins/NPCTypesPlugin.d.ts +26 -0
  216. package/dist/plugins/NPCTypesPlugin.d.ts.map +1 -0
  217. package/dist/plugins/NPCTypesPlugin.js +30 -0
  218. package/dist/plugins/NPCTypesPlugin.js.map +1 -0
  219. package/dist/plugins/PluginToken.d.ts +26 -0
  220. package/dist/plugins/PluginToken.d.ts.map +1 -0
  221. package/dist/plugins/PluginToken.js +22 -0
  222. package/dist/plugins/PluginToken.js.map +1 -0
  223. package/dist/plugins/SocialPlugin.d.ts +14 -0
  224. package/dist/plugins/SocialPlugin.d.ts.map +1 -0
  225. package/dist/plugins/SocialPlugin.js +16 -0
  226. package/dist/plugins/SocialPlugin.js.map +1 -0
  227. package/dist/plugins/SpawnPlugin.d.ts +15 -0
  228. package/dist/plugins/SpawnPlugin.d.ts.map +1 -0
  229. package/dist/plugins/SpawnPlugin.js +26 -0
  230. package/dist/plugins/SpawnPlugin.js.map +1 -0
  231. package/dist/plugins/SquadPlugin.d.ts +14 -0
  232. package/dist/plugins/SquadPlugin.d.ts.map +1 -0
  233. package/dist/plugins/SquadPlugin.js +16 -0
  234. package/dist/plugins/SquadPlugin.js.map +1 -0
  235. package/dist/plugins/SurgePlugin.d.ts +20 -0
  236. package/dist/plugins/SurgePlugin.d.ts.map +1 -0
  237. package/dist/plugins/SurgePlugin.js +22 -0
  238. package/dist/plugins/SurgePlugin.js.map +1 -0
  239. package/dist/plugins/TradePlugin.d.ts +16 -0
  240. package/dist/plugins/TradePlugin.d.ts.map +1 -0
  241. package/dist/plugins/TradePlugin.js +18 -0
  242. package/dist/plugins/TradePlugin.js.map +1 -0
  243. package/dist/plugins/index.d.ts +11 -0
  244. package/dist/plugins/index.d.ts.map +1 -0
  245. package/dist/plugins/index.js +10 -0
  246. package/dist/plugins/index.js.map +1 -0
  247. package/dist/plugins/pluginNames.d.ts +37 -0
  248. package/dist/plugins/pluginNames.d.ts.map +1 -0
  249. package/dist/plugins/pluginNames.js +28 -0
  250. package/dist/plugins/pluginNames.js.map +1 -0
  251. package/dist/plugins/presets.d.ts +31 -0
  252. package/dist/plugins/presets.d.ts.map +1 -0
  253. package/dist/plugins/presets.js +50 -0
  254. package/dist/plugins/presets.js.map +1 -0
  255. package/dist/ports/IDataLoader.d.ts +38 -0
  256. package/dist/ports/IDataLoader.d.ts.map +1 -0
  257. package/dist/ports/IDataLoader.js +12 -0
  258. package/dist/ports/IDataLoader.js.map +1 -0
  259. package/dist/ports/IEntityAdapter.d.ts +73 -0
  260. package/dist/ports/IEntityAdapter.d.ts.map +1 -0
  261. package/dist/ports/IEntityAdapter.js +36 -0
  262. package/dist/ports/IEntityAdapter.js.map +1 -0
  263. package/dist/ports/IEntityFactory.d.ts +66 -0
  264. package/dist/ports/IEntityFactory.d.ts.map +1 -0
  265. package/dist/ports/IEntityFactory.js +21 -0
  266. package/dist/ports/IEntityFactory.js.map +1 -0
  267. package/dist/ports/ILogger.d.ts +29 -0
  268. package/dist/ports/ILogger.d.ts.map +1 -0
  269. package/dist/ports/ILogger.js +2 -0
  270. package/dist/ports/ILogger.js.map +1 -0
  271. package/dist/ports/IPlayerPositionProvider.d.ts +20 -0
  272. package/dist/ports/IPlayerPositionProvider.d.ts.map +1 -0
  273. package/dist/ports/IPlayerPositionProvider.js +11 -0
  274. package/dist/ports/IPlayerPositionProvider.js.map +1 -0
  275. package/dist/ports/IRandom.d.ts +25 -0
  276. package/dist/ports/IRandom.d.ts.map +1 -0
  277. package/dist/ports/IRandom.js +39 -0
  278. package/dist/ports/IRandom.js.map +1 -0
  279. package/dist/ports/IRuntimeClock.d.ts +18 -0
  280. package/dist/ports/IRuntimeClock.d.ts.map +1 -0
  281. package/dist/ports/IRuntimeClock.js +2 -0
  282. package/dist/ports/IRuntimeClock.js.map +1 -0
  283. package/dist/ports/index.d.ts +12 -0
  284. package/dist/ports/index.d.ts.map +1 -0
  285. package/dist/ports/index.js +5 -0
  286. package/dist/ports/index.js.map +1 -0
  287. package/dist/registry/AIStateRegistry.d.ts +42 -0
  288. package/dist/registry/AIStateRegistry.d.ts.map +1 -0
  289. package/dist/registry/AIStateRegistry.js +27 -0
  290. package/dist/registry/AIStateRegistry.js.map +1 -0
  291. package/dist/registry/AnomalyTypeRegistry.d.ts +21 -0
  292. package/dist/registry/AnomalyTypeRegistry.d.ts.map +1 -0
  293. package/dist/registry/AnomalyTypeRegistry.js +20 -0
  294. package/dist/registry/AnomalyTypeRegistry.js.map +1 -0
  295. package/dist/registry/BehaviorSchemeRegistry.d.ts +21 -0
  296. package/dist/registry/BehaviorSchemeRegistry.d.ts.map +1 -0
  297. package/dist/registry/BehaviorSchemeRegistry.js +24 -0
  298. package/dist/registry/BehaviorSchemeRegistry.js.map +1 -0
  299. package/dist/registry/DamageTypeRegistry.d.ts +17 -0
  300. package/dist/registry/DamageTypeRegistry.d.ts.map +1 -0
  301. package/dist/registry/DamageTypeRegistry.js +24 -0
  302. package/dist/registry/DamageTypeRegistry.js.map +1 -0
  303. package/dist/registry/FactionRegistry.d.ts +41 -0
  304. package/dist/registry/FactionRegistry.d.ts.map +1 -0
  305. package/dist/registry/FactionRegistry.js +29 -0
  306. package/dist/registry/FactionRegistry.js.map +1 -0
  307. package/dist/registry/MonsterRegistry.d.ts +44 -0
  308. package/dist/registry/MonsterRegistry.d.ts.map +1 -0
  309. package/dist/registry/MonsterRegistry.js +43 -0
  310. package/dist/registry/MonsterRegistry.js.map +1 -0
  311. package/dist/registry/NPCTypeRegistry.d.ts +34 -0
  312. package/dist/registry/NPCTypeRegistry.d.ts.map +1 -0
  313. package/dist/registry/NPCTypeRegistry.js +20 -0
  314. package/dist/registry/NPCTypeRegistry.js.map +1 -0
  315. package/dist/registry/Registry.d.ts +44 -0
  316. package/dist/registry/Registry.d.ts.map +1 -0
  317. package/dist/registry/Registry.js +80 -0
  318. package/dist/registry/Registry.js.map +1 -0
  319. package/dist/registry/TaskTypeRegistry.d.ts +17 -0
  320. package/dist/registry/TaskTypeRegistry.d.ts.map +1 -0
  321. package/dist/registry/TaskTypeRegistry.js +16 -0
  322. package/dist/registry/TaskTypeRegistry.js.map +1 -0
  323. package/dist/registry/index.d.ts +19 -0
  324. package/dist/registry/index.d.ts.map +1 -0
  325. package/dist/registry/index.js +11 -0
  326. package/dist/registry/index.js.map +1 -0
  327. package/dist/schema/index.d.ts +3 -0
  328. package/dist/schema/index.d.ts.map +1 -0
  329. package/dist/schema/index.js +3 -0
  330. package/dist/schema/index.js.map +1 -0
  331. package/dist/schema/validators.d.ts +32 -0
  332. package/dist/schema/validators.d.ts.map +1 -0
  333. package/dist/schema/validators.js +249 -0
  334. package/dist/schema/validators.js.map +1 -0
  335. package/dist/spawn/SpawnRegistry.d.ts +48 -0
  336. package/dist/spawn/SpawnRegistry.d.ts.map +1 -0
  337. package/dist/spawn/SpawnRegistry.js +141 -0
  338. package/dist/spawn/SpawnRegistry.js.map +1 -0
  339. package/dist/spawn/index.d.ts +3 -0
  340. package/dist/spawn/index.d.ts.map +1 -0
  341. package/dist/spawn/index.js +3 -0
  342. package/dist/spawn/index.js.map +1 -0
  343. package/dist/terrain/SmartTerrain.d.ts +119 -0
  344. package/dist/terrain/SmartTerrain.d.ts.map +1 -0
  345. package/dist/terrain/SmartTerrain.js +124 -0
  346. package/dist/terrain/SmartTerrain.js.map +1 -0
  347. package/dist/terrain/TerrainBuilder.d.ts +44 -0
  348. package/dist/terrain/TerrainBuilder.d.ts.map +1 -0
  349. package/dist/terrain/TerrainBuilder.js +112 -0
  350. package/dist/terrain/TerrainBuilder.js.map +1 -0
  351. package/dist/terrain/Zone.d.ts +25 -0
  352. package/dist/terrain/Zone.d.ts.map +1 -0
  353. package/dist/terrain/Zone.js +29 -0
  354. package/dist/terrain/Zone.js.map +1 -0
  355. package/dist/terrain/index.d.ts +6 -0
  356. package/dist/terrain/index.d.ts.map +1 -0
  357. package/dist/terrain/index.js +5 -0
  358. package/dist/terrain/index.js.map +1 -0
  359. package/dist/time/TimeManager.d.ts +21 -0
  360. package/dist/time/TimeManager.d.ts.map +1 -0
  361. package/dist/time/TimeManager.js +41 -0
  362. package/dist/time/TimeManager.js.map +1 -0
  363. package/dist/time/index.d.ts +3 -0
  364. package/dist/time/index.d.ts.map +1 -0
  365. package/dist/time/index.js +2 -0
  366. package/dist/time/index.js.map +1 -0
  367. package/package.json +119 -0
@@ -0,0 +1,124 @@
1
+ /**
2
+ * SmartTerrain -- a Zone with job slots, capacity, and NPC fitness scoring.
3
+ *
4
+ * NPCs evaluate available terrains and select the one with the highest
5
+ * fitness score. The terrain tracks its occupants and enforces capacity.
6
+ */
7
+ import { distance, distanceSq } from '../core/Vec2';
8
+ import { DefaultRandom } from '../ports/IRandom';
9
+ import { Zone } from './Zone';
10
+ // ---------------------------------------------------------------------------
11
+ // Scoring constants
12
+ // ---------------------------------------------------------------------------
13
+ const DEFAULT_DISTANCE_PENALTY_DIVISOR = 100;
14
+ const DEFAULT_SHELTER_BONUS = 50;
15
+ const DEFAULT_RANK_MATCH_BONUS = 10;
16
+ const DEFAULT_SCORING_JITTER = 0;
17
+ // ---------------------------------------------------------------------------
18
+ // SmartTerrain
19
+ // ---------------------------------------------------------------------------
20
+ export class SmartTerrain extends Zone {
21
+ constructor(config) {
22
+ super(config.id, config.bounds, config.dangerLevel);
23
+ this.occupants = new Set();
24
+ this.capacity = config.capacity;
25
+ this.allowedFactions = new Set(config.allowedFactions ?? []);
26
+ this.isShelter = config.isShelter ?? false;
27
+ this.tags = new Set(config.tags ?? []);
28
+ this.jobs = config.jobs ?? [];
29
+ this.spawnPoints = config.spawnPoints ?? [];
30
+ this.patrolRoutes = buildRouteMap(config.patrolRoutes);
31
+ this.distancePenaltyDivisor = config.scoring?.distancePenaltyDivisor ?? DEFAULT_DISTANCE_PENALTY_DIVISOR;
32
+ this.useSquaredDistance = config.scoring?.useSquaredDistance ?? false;
33
+ this.distancePenaltySqDivisor = config.scoring?.distancePenaltySqDivisor
34
+ ?? (this.distancePenaltyDivisor * this.distancePenaltyDivisor);
35
+ this.shelterBonus = config.scoring?.shelterBonus ?? DEFAULT_SHELTER_BONUS;
36
+ this.rankMatchBonus = config.scoring?.rankMatchBonus ?? DEFAULT_RANK_MATCH_BONUS;
37
+ this.scoringJitter = config.scoring?.scoringJitter ?? DEFAULT_SCORING_JITTER;
38
+ this.random = config.random ?? new DefaultRandom();
39
+ }
40
+ /** Number of NPCs currently assigned to this terrain. */
41
+ get occupantCount() {
42
+ return this.occupants.size;
43
+ }
44
+ /** Whether the terrain can accept another NPC. */
45
+ get hasCapacity() {
46
+ return this.occupants.size < this.capacity;
47
+ }
48
+ /**
49
+ * Register an NPC as an occupant.
50
+ * Returns false if the terrain is already at capacity.
51
+ */
52
+ addOccupant(npcId) {
53
+ if (this.occupants.size >= this.capacity)
54
+ return false;
55
+ this.occupants.add(npcId);
56
+ return true;
57
+ }
58
+ /** Remove an NPC from the occupant set. */
59
+ removeOccupant(npcId) {
60
+ this.occupants.delete(npcId);
61
+ }
62
+ /** Check whether a given NPC is an occupant. */
63
+ hasOccupant(npcId) {
64
+ return this.occupants.has(npcId);
65
+ }
66
+ /** Read-only view of the current occupant set. */
67
+ getOccupants() {
68
+ return this.occupants;
69
+ }
70
+ /**
71
+ * Compute a fitness score for an NPC considering faction, distance,
72
+ * capacity, shelter status, and danger-to-rank matching.
73
+ *
74
+ * Scoring breakdown:
75
+ * - Base = remaining capacity (capacity - occupantCount)
76
+ * - Faction not allowed: -Infinity
77
+ * - Distance penalty: -distance / 100
78
+ * - Shelter bonus: +50 if isShelter
79
+ * - Rank >= dangerLevel: +10
80
+ */
81
+ scoreFitness(npcFaction, npcPosition, npcRank) {
82
+ if (!this.acceptsFaction(npcFaction))
83
+ return -Infinity;
84
+ let score = this.capacity - this.occupants.size;
85
+ if (this.useSquaredDistance) {
86
+ score -= distanceSq(npcPosition, this.center) / this.distancePenaltySqDivisor;
87
+ }
88
+ else {
89
+ score -= distance(npcPosition, this.center) / this.distancePenaltyDivisor;
90
+ }
91
+ if (this.isShelter) {
92
+ score += this.shelterBonus;
93
+ }
94
+ if (npcRank >= this.dangerLevel) {
95
+ score += this.rankMatchBonus;
96
+ }
97
+ if (this.scoringJitter > 0) {
98
+ score += (this.random.next() - 0.5) * 2 * this.scoringJitter;
99
+ }
100
+ return score;
101
+ }
102
+ /**
103
+ * Check whether a faction is allowed in this terrain.
104
+ * An empty allowedFactions set means all factions are accepted.
105
+ */
106
+ acceptsFaction(factionId) {
107
+ if (this.allowedFactions.size === 0)
108
+ return true;
109
+ return this.allowedFactions.has(factionId);
110
+ }
111
+ }
112
+ // ---------------------------------------------------------------------------
113
+ // Helpers
114
+ // ---------------------------------------------------------------------------
115
+ function buildRouteMap(routes) {
116
+ const map = new Map();
117
+ if (routes) {
118
+ for (const route of routes) {
119
+ map.set(route.id, route);
120
+ }
121
+ }
122
+ return map;
123
+ }
124
+ //# sourceMappingURL=SmartTerrain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmartTerrain.js","sourceRoot":"","sources":["../../src/terrain/SmartTerrain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Fluent builder for SmartTerrain configurations.
3
+ *
4
+ * Usage:
5
+ * const config = new TerrainBuilder('bar_rostok')
6
+ * .name('Bar "Rostok"')
7
+ * .bounds({ x: 100, y: 200, width: 300, height: 300 })
8
+ * .capacity(8)
9
+ * .allowFactions(['stalkers', 'duty'])
10
+ * .shelter(true)
11
+ * .tags(['indoor', 'settlement'])
12
+ * .addJob({ type: 'guard', slots: 2, position: { x: 120, y: 210 } })
13
+ * .build();
14
+ */
15
+ import type { IZoneBounds } from './Zone';
16
+ import type { ISmartTerrainConfig, IJobSlot, ISpawnPoint, IPatrolRouteConfig } from './SmartTerrain';
17
+ export declare class TerrainBuilder {
18
+ private readonly id;
19
+ private terrainName;
20
+ private terrainBounds;
21
+ private terrainDangerLevel;
22
+ private terrainCapacity;
23
+ private terrainFactions;
24
+ private terrainShelter;
25
+ private terrainTags;
26
+ private terrainJobs;
27
+ private terrainSpawnPoints;
28
+ private terrainPatrolRoutes;
29
+ constructor(id: string);
30
+ name(name: string): this;
31
+ bounds(b: IZoneBounds): this;
32
+ dangerLevel(level: number): this;
33
+ capacity(n: number): this;
34
+ allowFactions(factions: string[]): this;
35
+ shelter(isShelter: boolean): this;
36
+ tags(tags: string[]): this;
37
+ addJob(job: IJobSlot): this;
38
+ addSpawnPoint(sp: ISpawnPoint): this;
39
+ addPatrolRoute(route: IPatrolRouteConfig): this;
40
+ /** Validate required fields and return the SmartTerrain configuration. */
41
+ build(): ISmartTerrainConfig;
42
+ private validate;
43
+ }
44
+ //# sourceMappingURL=TerrainBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerrainBuilder.d.ts","sourceRoot":"","sources":["../../src/terrain/TerrainBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EACV,mBAAmB,EACnB,QAAQ,EACR,WAAW,EACX,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AAExB,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,mBAAmB,CAA4B;gBAE3C,EAAE,EAAE,MAAM;IAOtB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKxB,MAAM,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;IAK5B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKhC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAUzB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAKvC,OAAO,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAKjC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAK1B,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAK3B,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAKpC,cAAc,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAK/C,0EAA0E;IAC1E,KAAK,IAAI,mBAAmB;IA+B5B,OAAO,CAAC,QAAQ;CAejB"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Fluent builder for SmartTerrain configurations.
3
+ *
4
+ * Usage:
5
+ * const config = new TerrainBuilder('bar_rostok')
6
+ * .name('Bar "Rostok"')
7
+ * .bounds({ x: 100, y: 200, width: 300, height: 300 })
8
+ * .capacity(8)
9
+ * .allowFactions(['stalkers', 'duty'])
10
+ * .shelter(true)
11
+ * .tags(['indoor', 'settlement'])
12
+ * .addJob({ type: 'guard', slots: 2, position: { x: 120, y: 210 } })
13
+ * .build();
14
+ */
15
+ export class TerrainBuilder {
16
+ constructor(id) {
17
+ this.terrainName = '';
18
+ this.terrainDangerLevel = 0;
19
+ this.terrainCapacity = 0;
20
+ this.terrainFactions = [];
21
+ this.terrainShelter = false;
22
+ this.terrainTags = [];
23
+ this.terrainJobs = [];
24
+ this.terrainSpawnPoints = [];
25
+ this.terrainPatrolRoutes = [];
26
+ if (!id) {
27
+ throw new Error('[TerrainBuilder] id must not be empty');
28
+ }
29
+ this.id = id;
30
+ }
31
+ name(name) {
32
+ this.terrainName = name;
33
+ return this;
34
+ }
35
+ bounds(b) {
36
+ this.terrainBounds = b;
37
+ return this;
38
+ }
39
+ dangerLevel(level) {
40
+ this.terrainDangerLevel = level;
41
+ return this;
42
+ }
43
+ capacity(n) {
44
+ if (n < 0) {
45
+ throw new Error(`[TerrainBuilder] capacity must be non-negative, got ${n}`);
46
+ }
47
+ this.terrainCapacity = n;
48
+ return this;
49
+ }
50
+ allowFactions(factions) {
51
+ this.terrainFactions = [...factions];
52
+ return this;
53
+ }
54
+ shelter(isShelter) {
55
+ this.terrainShelter = isShelter;
56
+ return this;
57
+ }
58
+ tags(tags) {
59
+ this.terrainTags = [...tags];
60
+ return this;
61
+ }
62
+ addJob(job) {
63
+ this.terrainJobs.push(job);
64
+ return this;
65
+ }
66
+ addSpawnPoint(sp) {
67
+ this.terrainSpawnPoints.push(sp);
68
+ return this;
69
+ }
70
+ addPatrolRoute(route) {
71
+ this.terrainPatrolRoutes.push(route);
72
+ return this;
73
+ }
74
+ /** Validate required fields and return the SmartTerrain configuration. */
75
+ build() {
76
+ const errors = this.validate();
77
+ if (errors.length > 0) {
78
+ throw new Error(`[TerrainBuilder] Invalid terrain "${this.id}": ${errors.join('; ')}`);
79
+ }
80
+ return {
81
+ id: this.id,
82
+ name: this.terrainName,
83
+ bounds: this.terrainBounds,
84
+ dangerLevel: this.terrainDangerLevel,
85
+ capacity: this.terrainCapacity,
86
+ allowedFactions: this.terrainFactions.length > 0 ? [...this.terrainFactions] : undefined,
87
+ isShelter: this.terrainShelter || undefined,
88
+ tags: this.terrainTags.length > 0 ? [...this.terrainTags] : undefined,
89
+ jobs: this.terrainJobs.length > 0 ? [...this.terrainJobs] : undefined,
90
+ spawnPoints: this.terrainSpawnPoints.length > 0
91
+ ? [...this.terrainSpawnPoints]
92
+ : undefined,
93
+ patrolRoutes: this.terrainPatrolRoutes.length > 0
94
+ ? [...this.terrainPatrolRoutes]
95
+ : undefined,
96
+ };
97
+ }
98
+ validate() {
99
+ const errors = [];
100
+ if (!this.terrainName) {
101
+ errors.push('name is required');
102
+ }
103
+ if (!this.terrainBounds) {
104
+ errors.push('bounds is required');
105
+ }
106
+ if (this.terrainCapacity <= 0) {
107
+ errors.push('capacity must be a positive number');
108
+ }
109
+ return errors;
110
+ }
111
+ }
112
+ //# sourceMappingURL=TerrainBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerrainBuilder.js","sourceRoot":"","sources":["../../src/terrain/TerrainBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Base zone -- a named rectangular area in the world.
3
+ *
4
+ * Used as the foundation for SmartTerrain and other spatial constructs.
5
+ */
6
+ import type { Vec2 } from '../core/Vec2';
7
+ export interface IZoneBounds {
8
+ readonly x: number;
9
+ readonly y: number;
10
+ readonly width: number;
11
+ readonly height: number;
12
+ }
13
+ export declare class Zone {
14
+ readonly id: string;
15
+ readonly bounds: IZoneBounds;
16
+ readonly dangerLevel: number;
17
+ readonly metadata: ReadonlyMap<string, unknown>;
18
+ private readonly _center;
19
+ constructor(id: string, bounds: IZoneBounds, dangerLevel?: number, metadata?: Record<string, unknown>);
20
+ /** Check whether a point lies within this zone's bounds. */
21
+ contains(point: Vec2): boolean;
22
+ /** The geometric center of the zone (cached, frozen). */
23
+ get center(): Vec2;
24
+ }
25
+ //# sourceMappingURL=Zone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Zone.d.ts","sourceRoot":"","sources":["../../src/terrain/Zone.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,IAAI;IACf,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAO;gBAG7B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,EACnB,WAAW,SAAI,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYpC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO;IAS9B,yDAAyD;IACzD,IAAI,MAAM,IAAI,IAAI,CAEjB;CACF"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Base zone -- a named rectangular area in the world.
3
+ *
4
+ * Used as the foundation for SmartTerrain and other spatial constructs.
5
+ */
6
+ export class Zone {
7
+ constructor(id, bounds, dangerLevel = 0, metadata) {
8
+ this.id = id;
9
+ this.bounds = bounds;
10
+ this.dangerLevel = dangerLevel;
11
+ this.metadata = new Map(Object.entries(metadata ?? {}));
12
+ this._center = Object.freeze({
13
+ x: bounds.x + bounds.width / 2,
14
+ y: bounds.y + bounds.height / 2,
15
+ });
16
+ }
17
+ /** Check whether a point lies within this zone's bounds. */
18
+ contains(point) {
19
+ return (point.x >= this.bounds.x &&
20
+ point.x <= this.bounds.x + this.bounds.width &&
21
+ point.y >= this.bounds.y &&
22
+ point.y <= this.bounds.y + this.bounds.height);
23
+ }
24
+ /** The geometric center of the zone (cached, frozen). */
25
+ get center() {
26
+ return this._center;
27
+ }
28
+ }
29
+ //# sourceMappingURL=Zone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Zone.js","sourceRoot":"","sources":["../../src/terrain/Zone.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,OAAO,IAAI;IAOf,YACE,EAAU,EACV,MAAmB,EACnB,WAAW,GAAG,CAAC,EACf,QAAkC;QAElC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC;YAC9B,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC;SAChC,CAAC,CAAC;IACL,CAAC;IAED,4DAA4D;IAC5D,QAAQ,CAAC,KAAW;QAClB,OAAO,CACL,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;YAC5C,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAC9C,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export { Zone } from './Zone';
2
+ export type { IZoneBounds } from './Zone';
3
+ export { SmartTerrain } from './SmartTerrain';
4
+ export type { ISmartTerrainConfig, IScoringConfig, IJobSlot, IJobPreconditions, ISpawnPoint, IPatrolRouteConfig } from './SmartTerrain';
5
+ export { TerrainBuilder } from './TerrainBuilder';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/terrain/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACxI,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // terrain sub-path barrel
2
+ export { Zone } from './Zone';
3
+ export { SmartTerrain } from './SmartTerrain';
4
+ export { TerrainBuilder } from './TerrainBuilder';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/terrain/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { Clock } from '../core/Clock';
2
+ import type { IClockConfig, IClockState } from '../core/Clock';
3
+ import type { EventBus } from '../events/EventBus';
4
+ import type { ALifeEventPayloads } from '../events/ALifeEvents';
5
+ export interface ITimeManagerConfig {
6
+ /** Optional EventBus to receive 'time:hour_changed' and 'time:day_night_changed'. */
7
+ events?: EventBus<ALifeEventPayloads>;
8
+ /** Clock config (timeFactor, startHour, etc). onHourChanged/onDayNightChanged are managed internally. */
9
+ clockConfig?: Omit<IClockConfig, 'onHourChanged' | 'onDayNightChanged'>;
10
+ }
11
+ export declare class TimeManager {
12
+ private _clock;
13
+ private readonly _events;
14
+ constructor(config?: ITimeManagerConfig);
15
+ update(deltaMs: number): void;
16
+ get clock(): Clock;
17
+ serialize(): IClockState;
18
+ restore(state: IClockState): void;
19
+ private _buildCallbacks;
20
+ }
21
+ //# sourceMappingURL=TimeManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimeManager.d.ts","sourceRoot":"","sources":["../../src/time/TimeManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGhE,MAAM,WAAW,kBAAkB;IACjC,qFAAqF;IACrF,MAAM,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IACtC,yGAAyG;IACzG,WAAW,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,mBAAmB,CAAC,CAAC;CACzE;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;gBAEvD,MAAM,GAAE,kBAAuB;IAQ3C,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI7B,IAAI,KAAK,IAAI,KAAK,CAEjB;IAED,SAAS,IAAI,WAAW;IAIxB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAIjC,OAAO,CAAC,eAAe;CAaxB"}
@@ -0,0 +1,41 @@
1
+ // time/TimeManager.ts
2
+ // Standalone game-time manager.
3
+ // Wraps Clock with optional EventBus wiring — for games that do not use ALifeKernel.
4
+ import { Clock } from '../core/Clock';
5
+ import { ALifeEvents } from '../events/ALifeEvents';
6
+ export class TimeManager {
7
+ constructor(config = {}) {
8
+ this._events = config.events;
9
+ this._clock = new Clock({
10
+ ...(config.clockConfig ?? {}),
11
+ ...this._buildCallbacks(),
12
+ });
13
+ }
14
+ update(deltaMs) {
15
+ this._clock.update(deltaMs);
16
+ }
17
+ get clock() {
18
+ return this._clock;
19
+ }
20
+ serialize() {
21
+ return this._clock.serialize();
22
+ }
23
+ restore(state) {
24
+ this._clock = Clock.fromState(state, this._buildCallbacks());
25
+ }
26
+ _buildCallbacks() {
27
+ if (!this._events)
28
+ return {};
29
+ const events = this._events;
30
+ const self = this;
31
+ return {
32
+ onHourChanged: (hour, day) => {
33
+ events.emit(ALifeEvents.HOUR_CHANGED, { hour, day, isDay: self._clock.isDay });
34
+ },
35
+ onDayNightChanged: (isDay) => {
36
+ events.emit(ALifeEvents.DAY_NIGHT_CHANGED, { isDay });
37
+ },
38
+ };
39
+ }
40
+ }
41
+ //# sourceMappingURL=TimeManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimeManager.js","sourceRoot":"","sources":["../../src/time/TimeManager.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,gCAAgC;AAChC,qFAAqF;AAErF,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAItC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASpD,MAAM,OAAO,WAAW;IAItB,YAAY,SAA6B,EAAE;QACzC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC;YACtB,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;YAC7B,GAAG,IAAI,CAAC,eAAe,EAAE;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,OAAO,CAAC,KAAkB;QACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,OAAO;YACL,aAAa,EAAE,CAAC,IAAY,EAAE,GAAW,EAAE,EAAE;gBAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACjF,CAAC;YACD,iBAAiB,EAAE,CAAC,KAAc,EAAE,EAAE;gBACpC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACxD,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export { TimeManager } from './TimeManager';
2
+ export type { ITimeManagerConfig } from './TimeManager';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/time/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { TimeManager } from './TimeManager';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/time/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,119 @@
1
+ {
2
+ "name": "@alife-sdk/core",
3
+ "version": "0.1.0",
4
+ "description": "Framework-agnostic A-Life simulation and AI decision-making system",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./math": {
19
+ "types": "./dist/core/math/index.d.ts",
20
+ "import": "./dist/core/math/index.js"
21
+ },
22
+ "./events": {
23
+ "types": "./dist/events/index.d.ts",
24
+ "import": "./dist/events/index.js"
25
+ },
26
+ "./registry": {
27
+ "types": "./dist/registry/index.d.ts",
28
+ "import": "./dist/registry/index.js"
29
+ },
30
+ "./entity": {
31
+ "types": "./dist/entity/index.d.ts",
32
+ "import": "./dist/entity/index.js"
33
+ },
34
+ "./faction": {
35
+ "types": "./dist/faction/index.d.ts",
36
+ "import": "./dist/faction/index.js"
37
+ },
38
+ "./combat": {
39
+ "types": "./dist/combat/index.d.ts",
40
+ "import": "./dist/combat/index.js"
41
+ },
42
+ "./terrain": {
43
+ "types": "./dist/terrain/index.d.ts",
44
+ "import": "./dist/terrain/index.js"
45
+ },
46
+ "./movement": {
47
+ "types": "./dist/movement/index.d.ts",
48
+ "import": "./dist/movement/index.js"
49
+ },
50
+ "./spawn": {
51
+ "types": "./dist/spawn/index.d.ts",
52
+ "import": "./dist/spawn/index.js"
53
+ },
54
+ "./ai": {
55
+ "types": "./dist/ai/index.d.ts",
56
+ "import": "./dist/ai/index.js"
57
+ },
58
+ "./logger": {
59
+ "types": "./dist/logger/index.d.ts",
60
+ "import": "./dist/logger/index.js"
61
+ },
62
+ "./ports": {
63
+ "types": "./dist/ports/index.d.ts",
64
+ "import": "./dist/ports/index.js"
65
+ },
66
+ "./plugins": {
67
+ "types": "./dist/plugins/index.d.ts",
68
+ "import": "./dist/plugins/index.js"
69
+ },
70
+ "./schema": {
71
+ "types": "./dist/schema/index.d.ts",
72
+ "import": "./dist/schema/index.js"
73
+ },
74
+ "./config": {
75
+ "types": "./dist/config/index.d.ts",
76
+ "import": "./dist/config/index.js"
77
+ },
78
+ "./navigation": {
79
+ "types": "./dist/navigation/index.d.ts",
80
+ "import": "./dist/navigation/index.js"
81
+ }
82
+ },
83
+ "keywords": [
84
+ "alife",
85
+ "game-ai",
86
+ "simulation",
87
+ "npc",
88
+ "behavior",
89
+ "state-machine",
90
+ "goap"
91
+ ],
92
+ "license": "MIT",
93
+ "author": "Eugene Rusakov",
94
+ "repository": {
95
+ "type": "git",
96
+ "url": "https://github.com/eurusik/alife-sdk.git",
97
+ "directory": "packages/alife-core"
98
+ },
99
+ "homepage": "https://github.com/eurusik/alife-sdk#readme",
100
+ "bugs": {
101
+ "url": "https://github.com/eurusik/alife-sdk/issues"
102
+ },
103
+ "engines": {
104
+ "node": ">=20.0.0"
105
+ },
106
+ "publishConfig": {
107
+ "access": "public"
108
+ },
109
+ "devDependencies": {
110
+ "typescript": "^5.9.3",
111
+ "vitest": "^4.0.18"
112
+ },
113
+ "scripts": {
114
+ "build": "tsc",
115
+ "dev": "tsc --watch",
116
+ "test": "vitest run",
117
+ "test:watch": "vitest"
118
+ }
119
+ }