@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eugene Rusakov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # @alife-sdk/core
2
+
3
+ Framework-agnostic A-Life simulation and AI decision-making system.
4
+
5
+ Zero external dependencies. Works with Phaser, Unity, Node.js, or any other runtime.
6
+
7
+ ```
8
+ npm install @alife-sdk/core
9
+ ```
10
+
11
+ ---
12
+
13
+ ## What this package does
14
+
15
+ `@alife-sdk/core` provides the complete foundation for a living game world:
16
+
17
+ - **NPC AI** — finite state machines, GOAP planners, memory and perception systems
18
+ - **A-Life simulation** — offline NPC brains, terrain selection, spawn cooldowns, faction diplomacy
19
+ - **Game clock** — accelerated in-game time, day/night cycle, hour events
20
+ - **World graph** — waypoint graph with A* pathfinding for offline NPC movement
21
+ - **Plugin system** — extend the kernel with your own domain features
22
+
23
+ The package is intentionally engine-agnostic. It never imports Phaser,
24
+ renders sprites, or touches the DOM. All engine interaction goes through
25
+ **ports** — narrow interfaces you implement once for your engine.
26
+
27
+ ---
28
+
29
+ ## Quick start
30
+
31
+ > The SDK ships **interfaces only** for engine adapters — `IEntityAdapter`,
32
+ > `IEntityFactory`, `IDataLoader`, etc. You implement them once for your engine.
33
+ > The example below uses placeholder names; replace them with your own implementations.
34
+ > See [`ports/README.md`](src/ports/README.md) for full interface specs and a Phaser example.
35
+
36
+ ```ts
37
+ import { ALifeKernel, Ports } from '@alife-sdk/core';
38
+ import { fullPreset, Plugins } from '@alife-sdk/core/plugins';
39
+
40
+ // 1. Create the kernel
41
+ const kernel = new ALifeKernel();
42
+
43
+ // 2. Register engine adapters (optional — kernel auto-provides no-ops if omitted)
44
+ // (MyEntityAdapter / MyEntityFactory — your implementations of
45
+ // IEntityAdapter / IEntityFactory from @alife-sdk/core/ports)
46
+ kernel.provide(Ports.EntityAdapter, new MyEntityAdapter(scene));
47
+ kernel.provide(Ports.EntityFactory, new MyEntityFactory(scene));
48
+ kernel.provide(Ports.PlayerPosition, { getPlayerPosition: () => ({ x: player.x, y: player.y }) });
49
+ // Ports.RuntimeClock and Ports.Random are also optional (SDK provides defaults)
50
+
51
+ // 3. Install built-in plugins
52
+ fullPreset(kernel);
53
+
54
+ // 4. Register game data (before init)
55
+ const factions = kernel.getPlugin(Plugins.FACTIONS).factions;
56
+ factions.register('stalker', { name: 'Stalker', baseRelations: { bandit: -80 } });
57
+ factions.register('bandit', { name: 'Bandit', baseRelations: { stalker: -80 } });
58
+
59
+ // 5. Init — validates ports, freezes registries, returns DiagnosticsCollector
60
+ const diag = kernel.init();
61
+
62
+ // 6. Start — enables frame-based update()
63
+ kernel.start();
64
+
65
+ // 7. Game loop
66
+ function update(deltaMs: number): void {
67
+ kernel.update(deltaMs);
68
+ }
69
+
70
+ // 8. Save / load
71
+ const save = kernel.serialize();
72
+ kernel.restoreState(save);
73
+
74
+ // 9. Cleanup
75
+ kernel.destroy();
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Sub-path imports
81
+
82
+ Each module has its own import path for optimal tree-shaking:
83
+
84
+ | Import path | What's inside | Module docs |
85
+ |-------------|--------------|-------------|
86
+ | `@alife-sdk/core` | `ALifeKernel`, `Clock`, `SpatialGrid`, `Ports` | [core/](src/core/) |
87
+ | `@alife-sdk/core/ai` | `StateMachine`, `MemoryBank`, `DangerManager`, `GOAPPlanner` | [ai/](src/ai/README.md) |
88
+ | `@alife-sdk/core/combat` | `DamageInstance`, `MoraleTracker`, `ImmunityProfile` | [combat/](src/combat/README.md) |
89
+ | `@alife-sdk/core/config` | `createDefaultConfig`, `IALifeConfig` | [config/](src/config/README.md) |
90
+ | `@alife-sdk/core/entity` | `IEntity`, `IComponent` | [entity/](src/entity/README.md) |
91
+ | `@alife-sdk/core/events` | `EventBus`, `ALifeEvents`, `ALifeEventPayloads` | [events/](src/events/README.md) |
92
+ | `@alife-sdk/core/faction` | `Faction`, `FactionBuilder` | [faction/](src/faction/README.md) |
93
+ | `@alife-sdk/core/logger` | `Logger`, `LogLevel`, `LogChannel` | [logger/](src/logger/README.md) |
94
+ | `@alife-sdk/core/movement` | `PatrolRouteTracker`, `MonsterHome` | [movement/](src/movement/README.md) |
95
+ | `@alife-sdk/core/navigation` | `LevelGraph`, `NPCGraphMover` | [navigation/](src/navigation/README.md) |
96
+ | `@alife-sdk/core/plugins` | `IALifePlugin`, built-in plugins, `Plugins` tokens | [plugins/](src/plugins/README.md) |
97
+ | `@alife-sdk/core/ports` | `IEntityAdapter`, `IDataLoader`, `IRandom`, … | [ports/](src/ports/README.md) |
98
+ | `@alife-sdk/core/registry` | `Registry`, `FactionRegistry`, `AIStateRegistry`, … | [registry/](src/registry/README.md) |
99
+ | `@alife-sdk/core/schema` | `validateMonsterDefinition`, assertion helpers | [schema/](src/schema/README.md) |
100
+ | `@alife-sdk/core/spawn` | `SpawnRegistry` | [spawn/](src/spawn/README.md) |
101
+ | `@alife-sdk/core/terrain` | `Zone`, `SmartTerrain`, `TerrainBuilder` | [terrain/](src/terrain/README.md) |
102
+ | `@alife-sdk/core/time` | `TimeManager` | [time/](src/time/README.md) |
103
+
104
+ ---
105
+
106
+ ## Architecture
107
+
108
+ ```
109
+ ┌─────────────────────────────────┐
110
+ │ ALifeKernel │
111
+ │ clock · events · logger · ports │
112
+ └──────────────┬──────────────────┘
113
+ │ kernel.use(plugin)
114
+ ┌────────────────────────┼────────────────────────┐
115
+ │ │ │
116
+ FactionsPlugin NPCTypesPlugin SpawnPlugin
117
+ FactionRegistry NPCTypeRegistry SpawnRegistry
118
+ │ │ │
119
+ └────────────────────────┼────────────────────────┘
120
+
121
+ ┌────────────────────────┼────────────────────────┐
122
+ │ │ │
123
+ StateMachine MemoryBank GOAPPlanner
124
+ (18 AI states) (4 channels, decay) (A* on WorldState)
125
+ │ │ │
126
+ └────────────────────────┼────────────────────────┘
127
+
128
+ ┌────────────────────────┼────────────────────────┐
129
+ │ │ │
130
+ LevelGraph SmartTerrain Faction
131
+ (A* pathfinding) (capacity + fitness) (two-layer relations)
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Key concepts
137
+
138
+ ### Ports — engine adapter pattern
139
+
140
+ The kernel never calls Phaser or any engine API directly. Instead, it calls
141
+ **ports** — interfaces you implement to bridge the SDK to your engine.
142
+
143
+ All ports are optional — the kernel auto-provides silent no-op defaults for
144
+ engine ports if you don't supply real implementations. This means
145
+ `new ALifeKernel().init()` works with zero configuration for offline
146
+ simulation, persistence, and unit tests.
147
+
148
+ | Port | Interface | Default | Purpose |
149
+ |------|-----------|---------|---------|
150
+ | Entity adapter | `IEntityAdapter` | no-op | Read/write entity position, visibility, components |
151
+ | Entity factory | `IEntityFactory` | no-op | Create and destroy game objects |
152
+ | Player position | `IPlayerPositionProvider` | `{x:0,y:0}` | Online/offline radius check each tick |
153
+ | Runtime clock | `IRuntimeClock` | `Date.now()` | Real-time ms for cooldown timers |
154
+ | Random | `IRandom` | `Math.random()` | PRNG for simulation randomness |
155
+
156
+ See [`ports/README.md`](src/ports/README.md) for implementation examples.
157
+
158
+ ### Plugin system
159
+
160
+ The kernel is minimal by design. All domain features live in plugins that
161
+ you install with `kernel.use(plugin)`. Built-in plugins cover factions,
162
+ NPC types, combat schemas, spawning, monsters, and anomalies.
163
+
164
+ Write your own plugin by implementing `IALifePlugin`:
165
+
166
+ ```ts
167
+ class WeatherPlugin implements IALifePlugin {
168
+ readonly name = 'weather';
169
+ install(kernel: ALifeKernel): void { ... }
170
+ update(deltaMs: number): void { ... }
171
+ destroy(): void { ... }
172
+ }
173
+ kernel.use(new WeatherPlugin());
174
+ ```
175
+
176
+ See [`plugins/README.md`](src/plugins/README.md).
177
+
178
+ ### Event bus
179
+
180
+ All simulation events are delivered via a deferred `EventBus`.
181
+ `emit()` queues an event; `flush()` delivers it — called automatically by
182
+ `kernel.update()` at the end of each frame.
183
+
184
+ ```ts
185
+ kernel.events.on(ALifeEvents.NPC_DIED, ({ npcId, killedBy }) => {
186
+ questSystem.onNpcKilled(npcId);
187
+ });
188
+ ```
189
+
190
+ 38 typed events across 9 categories: A-Life, AI, Surge, Anomaly, Squad,
191
+ Faction, Time, Social, Monster. See [`events/README.md`](src/events/README.md).
192
+
193
+ ### AI — StateMachine + GOAP
194
+
195
+ Every online NPC runs a `StateMachine` over states registered in `AIStateRegistry`.
196
+ Each state has `enter / update / exit` handlers and optional auto-transition rules.
197
+
198
+ Elite NPCs (rank ≥ 5) additionally run a `GOAPPlanner` — an A* planner over
199
+ a `WorldState` bitmask that picks the optimal action sequence to achieve a goal.
200
+
201
+ See [`ai/README.md`](src/ai/README.md).
202
+
203
+ ### Offline simulation — LevelGraph + SmartTerrain
204
+
205
+ NPCs outside the player's view radius move through a `LevelGraph` (waypoint
206
+ graph with A*) without needing a full physics update. Each offline NPC gets
207
+ a `NPCGraphMover` cursor that interpolates world position along graph edges.
208
+
209
+ NPCs choose destinations by scoring all `SmartTerrain` instances via
210
+ `scoreFitness()` — a function of distance, capacity, shelter bonus, and
211
+ danger-vs-rank match.
212
+
213
+ ---
214
+
215
+ ## Lifecycle
216
+
217
+ ```
218
+ kernel.provide(port) ← register port adapters
219
+
220
+ kernel.use(plugin) ← register plugins
221
+
222
+ kernel.init() ← validate ports, freeze registries, call plugin.init()
223
+
224
+ kernel.start() ← enable frame-based update()
225
+
226
+ kernel.update(delta) ← each frame: tick plugins → flush events
227
+
228
+ kernel.serialize() ← capture state for save
229
+ kernel.restoreState() ← restore from save
230
+
231
+ kernel.destroy() ← cleanup, call plugin.destroy() in reverse order
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Testing
237
+
238
+ ```
239
+ pnpm test --filter @alife-sdk/core
240
+ ```
241
+
242
+ The SDK is designed to be test-friendly:
243
+ - Engine ports (`EntityAdapter`, `PlayerPosition`, `EntityFactory`) auto-provide
244
+ no-ops — no boilerplate needed for offline/persistence tests
245
+ - `IRandom` port → inject `SeededRandom` for deterministic results
246
+ - `IRuntimeClock` port → inject a frozen clock
247
+
248
+ ```ts
249
+ // Minimal test kernel — no provide() needed
250
+ const kernel = new ALifeKernel();
251
+ kernel.init();
252
+ kernel.step(10);
253
+
254
+ // Override only what your test actually needs
255
+ const kernel = new ALifeKernel();
256
+ kernel.provide(Ports.Random, new SeededRandom(42));
257
+ kernel.init();
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Module map
263
+
264
+ ```
265
+ src/
266
+ ├── core/ ALifeKernel, Clock, SpatialGrid, Vec2, PortRegistry, Diagnostics
267
+ ├── ai/ StateMachine, MemorySystem, DangerManager, GOAPPlanner/Action/WorldState
268
+ ├── combat/ DamageInstance, ImmunityProfile, MoraleTracker
269
+ ├── config/ IALifeConfig, createDefaultConfig
270
+ ├── entity/ IEntity, IComponent (interfaces only)
271
+ ├── events/ EventBus, ALifeEvents, ALifeEventPayloads
272
+ ├── faction/ Faction, FactionBuilder, IFactionState
273
+ ├── logger/ Logger, LogLevel, LogChannel, ILogEntry
274
+ ├── movement/ PatrolRouteTracker, RouteType, MonsterHome
275
+ ├── navigation/ LevelGraph, NPCGraphMover
276
+ ├── plugins/ IALifePlugin, built-in plugins, PluginToken, presets
277
+ ├── ports/ IEntityAdapter, IEntityFactory, IRandom, IRuntimeClock, IDataLoader, ILogger
278
+ ├── registry/ Registry, FactionRegistry, NPCTypeRegistry, MonsterRegistry, AIStateRegistry, …
279
+ ├── schema/ validateMonsterDefinition, validateFactionDefinition, assertion helpers
280
+ ├── spawn/ SpawnRegistry
281
+ ├── terrain/ Zone, SmartTerrain, TerrainBuilder
282
+ └── time/ TimeManager
283
+ ```
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Typed danger system with spatial awareness.
3
+ *
4
+ * DangerManager maintains a set of active danger zones in the world.
5
+ * Each danger has a type, position, radius, threat score, and time-to-live.
6
+ * NPCs query this manager to find nearby threats and compute safe
7
+ * movement directions.
8
+ *
9
+ * All spatial queries use squared-distance math for performance.
10
+ */
11
+ import type { Vec2 } from '../core/Vec2';
12
+ export declare const DangerType: {
13
+ readonly GRENADE: "grenade";
14
+ readonly GUNFIRE: "gunfire";
15
+ readonly EXPLOSION: "explosion";
16
+ readonly CORPSE: "corpse";
17
+ readonly ANOMALY: "anomaly";
18
+ readonly ATTACK_SOUND: "attack_sound";
19
+ };
20
+ export type DangerType = (typeof DangerType)[keyof typeof DangerType] | (string & {});
21
+ export interface IDangerEntry {
22
+ readonly id: string;
23
+ readonly type: DangerType;
24
+ readonly position: Vec2;
25
+ readonly radius: number;
26
+ /** Urgency score in [0, 1]. Higher = more threatening. */
27
+ readonly threatScore: number;
28
+ /** Milliseconds remaining before this danger expires. */
29
+ readonly remainingMs: number;
30
+ }
31
+ export declare class DangerManager {
32
+ private readonly dangers;
33
+ private readonly defaultThreshold;
34
+ constructor(defaultThreshold?: number);
35
+ /** Register a danger zone. Replaces an existing danger with the same ID. */
36
+ addDanger(entry: IDangerEntry): void;
37
+ /** Remove a danger by ID. */
38
+ removeDanger(id: string): void;
39
+ /**
40
+ * Get total threat score at a position.
41
+ *
42
+ * Sums the threat scores of all dangers whose radius covers the position.
43
+ * Result is not clamped -- may exceed 1.0 when multiple dangers overlap.
44
+ */
45
+ getThreatAt(position: Vec2): number;
46
+ /** Get all dangers within the given radius of a position. */
47
+ getDangersNear(position: Vec2, radius: number): IDangerEntry[];
48
+ /**
49
+ * Find the safest direction to move (away from threats).
50
+ *
51
+ * Computes a weighted repulsion vector from all nearby dangers.
52
+ * Each danger contributes a repulsion force inversely proportional to
53
+ * its distance and proportional to its threat score.
54
+ *
55
+ * Returns ZERO if no dangers are active.
56
+ */
57
+ getSafeDirection(position: Vec2): Vec2;
58
+ /** Tick: decay danger durations, remove expired entries. */
59
+ update(deltaMs: number): void;
60
+ /**
61
+ * Check if a position is dangerous (total threat exceeds threshold).
62
+ *
63
+ * @param position - World-space position to test.
64
+ * @param threshold - Minimum threat level to consider dangerous.
65
+ */
66
+ isDangerous(position: Vec2, threshold?: number): boolean;
67
+ get activeDangerCount(): number;
68
+ serialize(): IDangerEntry[];
69
+ restore(entries: IDangerEntry[]): void;
70
+ }
71
+ //# sourceMappingURL=DangerManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DangerManager.d.ts","sourceRoot":"","sources":["../../src/ai/DangerManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAOzC,eAAO,MAAM,UAAU;;;;;;;CAOb,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAMtF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AA0BD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,gBAAgB,GAAE,MAAiC;IAQ/D,4EAA4E;IAC5E,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAIpC,6BAA6B;IAC7B,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ9B;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM;IAcnC,6DAA6D;IAC7D,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE;IAc9D;;;;;;;;OAQG;IACH,gBAAgB,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IA8CtC,4DAA4D;IAC5D,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAiB7B;;;;;OAKG;IACH,WAAW,CACT,QAAQ,EAAE,IAAI,EACd,SAAS,GAAE,MAA8B,GACxC,OAAO;IAeV,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAMD,SAAS,IAAI,YAAY,EAAE;IAI3B,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;CAMvC"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Typed danger system with spatial awareness.
3
+ *
4
+ * DangerManager maintains a set of active danger zones in the world.
5
+ * Each danger has a type, position, radius, threat score, and time-to-live.
6
+ * NPCs query this manager to find nearby threats and compute safe
7
+ * movement directions.
8
+ *
9
+ * All spatial queries use squared-distance math for performance.
10
+ */
11
+ import { distanceSq, ZERO } from '../core/Vec2';
12
+ // ---------------------------------------------------------------------------
13
+ // Danger type
14
+ // ---------------------------------------------------------------------------
15
+ export const DangerType = {
16
+ GRENADE: 'grenade',
17
+ GUNFIRE: 'gunfire',
18
+ EXPLOSION: 'explosion',
19
+ CORPSE: 'corpse',
20
+ ANOMALY: 'anomaly',
21
+ ATTACK_SOUND: 'attack_sound',
22
+ };
23
+ // ---------------------------------------------------------------------------
24
+ // Constants
25
+ // ---------------------------------------------------------------------------
26
+ const DEFAULT_THREAT_THRESHOLD = 0.1;
27
+ // ---------------------------------------------------------------------------
28
+ // DangerManager
29
+ // ---------------------------------------------------------------------------
30
+ export class DangerManager {
31
+ constructor(defaultThreshold = DEFAULT_THREAT_THRESHOLD) {
32
+ this.dangers = new Map();
33
+ this.defaultThreshold = defaultThreshold;
34
+ }
35
+ // -----------------------------------------------------------------------
36
+ // Mutation
37
+ // -----------------------------------------------------------------------
38
+ /** Register a danger zone. Replaces an existing danger with the same ID. */
39
+ addDanger(entry) {
40
+ this.dangers.set(entry.id, { ...entry });
41
+ }
42
+ /** Remove a danger by ID. */
43
+ removeDanger(id) {
44
+ this.dangers.delete(id);
45
+ }
46
+ // -----------------------------------------------------------------------
47
+ // Spatial queries
48
+ // -----------------------------------------------------------------------
49
+ /**
50
+ * Get total threat score at a position.
51
+ *
52
+ * Sums the threat scores of all dangers whose radius covers the position.
53
+ * Result is not clamped -- may exceed 1.0 when multiple dangers overlap.
54
+ */
55
+ getThreatAt(position) {
56
+ let totalThreat = 0;
57
+ for (const danger of this.dangers.values()) {
58
+ const dsq = distanceSq(position, danger.position);
59
+ const rSq = danger.radius * danger.radius;
60
+ if (dsq <= rSq) {
61
+ totalThreat += danger.threatScore;
62
+ }
63
+ }
64
+ return totalThreat;
65
+ }
66
+ /** Get all dangers within the given radius of a position. */
67
+ getDangersNear(position, radius) {
68
+ const result = [];
69
+ const searchRadiusSq = radius * radius;
70
+ for (const danger of this.dangers.values()) {
71
+ const dsq = distanceSq(position, danger.position);
72
+ if (dsq <= searchRadiusSq) {
73
+ result.push(danger);
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ /**
79
+ * Find the safest direction to move (away from threats).
80
+ *
81
+ * Computes a weighted repulsion vector from all nearby dangers.
82
+ * Each danger contributes a repulsion force inversely proportional to
83
+ * its distance and proportional to its threat score.
84
+ *
85
+ * Returns ZERO if no dangers are active.
86
+ */
87
+ getSafeDirection(position) {
88
+ let repulsionX = 0;
89
+ let repulsionY = 0;
90
+ let hasDangers = false;
91
+ for (const danger of this.dangers.values()) {
92
+ const dsq = distanceSq(position, danger.position);
93
+ const rSq = danger.radius * danger.radius;
94
+ if (dsq > rSq)
95
+ continue;
96
+ hasDangers = true;
97
+ const dist = Math.sqrt(dsq);
98
+ if (dist < 1) {
99
+ // Directly on top of danger -- derive a direction from danger position
100
+ // to avoid a constant northeast bias.
101
+ const angle = ((danger.position.x * 73 + danger.position.y * 37) % 360) * (Math.PI / 180);
102
+ repulsionX += Math.cos(angle) * danger.threatScore;
103
+ repulsionY += Math.sin(angle) * danger.threatScore;
104
+ continue;
105
+ }
106
+ // Direction from danger to position (away from danger), inlined.
107
+ const dx = position.x - danger.position.x;
108
+ const dy = position.y - danger.position.y;
109
+ // Weight by threat score and inverse distance.
110
+ const weight = danger.threatScore / dist;
111
+ repulsionX += dx * weight;
112
+ repulsionY += dy * weight;
113
+ }
114
+ if (!hasDangers)
115
+ return ZERO;
116
+ // Inline normalize — avoid allocating intermediate {x, y}.
117
+ const mag = Math.sqrt(repulsionX * repulsionX + repulsionY * repulsionY);
118
+ if (mag === 0)
119
+ return ZERO;
120
+ return { x: repulsionX / mag, y: repulsionY / mag };
121
+ }
122
+ // -----------------------------------------------------------------------
123
+ // Update
124
+ // -----------------------------------------------------------------------
125
+ /** Tick: decay danger durations, remove expired entries. */
126
+ update(deltaMs) {
127
+ const toDelete = [];
128
+ for (const [id, danger] of this.dangers) {
129
+ danger.remainingMs -= deltaMs;
130
+ if (danger.remainingMs <= 0) {
131
+ toDelete.push(id);
132
+ }
133
+ }
134
+ for (const id of toDelete) {
135
+ this.dangers.delete(id);
136
+ }
137
+ }
138
+ // -----------------------------------------------------------------------
139
+ // Convenience checks
140
+ // -----------------------------------------------------------------------
141
+ /**
142
+ * Check if a position is dangerous (total threat exceeds threshold).
143
+ *
144
+ * @param position - World-space position to test.
145
+ * @param threshold - Minimum threat level to consider dangerous.
146
+ */
147
+ isDangerous(position, threshold = this.defaultThreshold) {
148
+ let totalThreat = 0;
149
+ for (const danger of this.dangers.values()) {
150
+ const dsq = distanceSq(position, danger.position);
151
+ const rSq = danger.radius * danger.radius;
152
+ if (dsq <= rSq) {
153
+ totalThreat += danger.threatScore;
154
+ if (totalThreat >= threshold)
155
+ return true;
156
+ }
157
+ }
158
+ return false;
159
+ }
160
+ get activeDangerCount() {
161
+ return this.dangers.size;
162
+ }
163
+ // -----------------------------------------------------------------------
164
+ // Serialisation
165
+ // -----------------------------------------------------------------------
166
+ serialize() {
167
+ return [...this.dangers.values()];
168
+ }
169
+ restore(entries) {
170
+ this.dangers.clear();
171
+ for (const entry of entries) {
172
+ this.dangers.set(entry.id, { ...entry });
173
+ }
174
+ }
175
+ }
176
+ //# sourceMappingURL=DangerManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DangerManager.js","sourceRoot":"","sources":["../../src/ai/DangerManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Abstract GOAP action base.
3
+ *
4
+ * Each concrete action encodes:
5
+ * - id: Unique string identifier for logging and plan inspection.
6
+ * - cost: Planner cost. Lower = preferred path.
7
+ * - preconditions: WorldState properties that must be true before execution.
8
+ * - effects: WorldState properties this action produces on success.
9
+ *
10
+ * Execution lifecycle per action:
11
+ * 1. isValid() -- real-time guard (can bail on stale conditions)
12
+ * 2. execute() -- called every tick; returns RUNNING / SUCCESS / FAILURE
13
+ * 3. abort() -- called when the action is interrupted (default no-op)
14
+ */
15
+ import type { WorldState } from './WorldState';
16
+ import type { IEntity } from '../entity/IEntity';
17
+ export declare const ActionStatus: {
18
+ readonly RUNNING: "running";
19
+ readonly SUCCESS: "success";
20
+ readonly FAILURE: "failure";
21
+ };
22
+ export type ActionStatus = (typeof ActionStatus)[keyof typeof ActionStatus];
23
+ export declare abstract class GOAPAction {
24
+ /** Unique action identifier for logging and plan inspection. */
25
+ abstract readonly id: string;
26
+ /** Planner cost. Lower cost = preferred path. */
27
+ abstract readonly cost: number;
28
+ /** Preconditions that must be true for this action to be valid. */
29
+ abstract getPreconditions(): WorldState;
30
+ /** Effects this action has on the world state when it completes. */
31
+ abstract getEffects(): WorldState;
32
+ /** Check if the action can currently execute (real-time guard). */
33
+ abstract isValid(entity: IEntity): boolean;
34
+ /**
35
+ * Execute one tick of this action.
36
+ *
37
+ * @param entity - The entity executing this action.
38
+ * @param delta - Milliseconds elapsed since the last tick.
39
+ * @returns Status indicating whether to continue, succeed, or fail.
40
+ */
41
+ abstract execute(entity: IEntity, delta: number): ActionStatus;
42
+ /** Called when the action is interrupted. Override for cleanup. */
43
+ abort(_entity: IEntity): void;
44
+ }
45
+ //# sourceMappingURL=GOAPAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GOAPAction.d.ts","sourceRoot":"","sources":["../../src/ai/GOAPAction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMjD,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAM5E,8BAAsB,UAAU;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAE7B,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAE/B,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,IAAI,UAAU;IAEvC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,IAAI,UAAU;IAEjC,mEAAmE;IACnE,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO;IAE1C;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY;IAE9D,mEAAmE;IACnE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAG9B"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Abstract GOAP action base.
3
+ *
4
+ * Each concrete action encodes:
5
+ * - id: Unique string identifier for logging and plan inspection.
6
+ * - cost: Planner cost. Lower = preferred path.
7
+ * - preconditions: WorldState properties that must be true before execution.
8
+ * - effects: WorldState properties this action produces on success.
9
+ *
10
+ * Execution lifecycle per action:
11
+ * 1. isValid() -- real-time guard (can bail on stale conditions)
12
+ * 2. execute() -- called every tick; returns RUNNING / SUCCESS / FAILURE
13
+ * 3. abort() -- called when the action is interrupted (default no-op)
14
+ */
15
+ // ---------------------------------------------------------------------------
16
+ // Action status
17
+ // ---------------------------------------------------------------------------
18
+ export const ActionStatus = {
19
+ RUNNING: 'running',
20
+ SUCCESS: 'success',
21
+ FAILURE: 'failure',
22
+ };
23
+ // ---------------------------------------------------------------------------
24
+ // Abstract base class
25
+ // ---------------------------------------------------------------------------
26
+ export class GOAPAction {
27
+ /** Called when the action is interrupted. Override for cleanup. */
28
+ abort(_entity) {
29
+ // Default no-op. Concrete actions override for cleanup.
30
+ }
31
+ }
32
+ //# sourceMappingURL=GOAPAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GOAPAction.js","sourceRoot":"","sources":["../../src/ai/GOAPAction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;CACV,CAAC;AAIX,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,MAAM,OAAgB,UAAU;IAyB9B,mEAAmE;IACnE,KAAK,CAAC,OAAgB;QACpB,wDAAwD;IAC1D,CAAC;CACF"}