@alife-sdk/ai 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 (395) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +385 -0
  3. package/dist/animation/AnimationController.d.ts +60 -0
  4. package/dist/animation/AnimationController.d.ts.map +1 -0
  5. package/dist/animation/AnimationController.js +71 -0
  6. package/dist/animation/AnimationController.js.map +1 -0
  7. package/dist/animation/AnimationSelector.d.ts +108 -0
  8. package/dist/animation/AnimationSelector.d.ts.map +1 -0
  9. package/dist/animation/AnimationSelector.js +194 -0
  10. package/dist/animation/AnimationSelector.js.map +1 -0
  11. package/dist/animation/index.d.ts +5 -0
  12. package/dist/animation/index.d.ts.map +1 -0
  13. package/dist/animation/index.js +4 -0
  14. package/dist/animation/index.js.map +1 -0
  15. package/dist/combat/CombatTransitionChain.d.ts +95 -0
  16. package/dist/combat/CombatTransitionChain.d.ts.map +1 -0
  17. package/dist/combat/CombatTransitionChain.js +117 -0
  18. package/dist/combat/CombatTransitionChain.js.map +1 -0
  19. package/dist/combat/LoadoutBuilder.d.ts +83 -0
  20. package/dist/combat/LoadoutBuilder.d.ts.map +1 -0
  21. package/dist/combat/LoadoutBuilder.js +213 -0
  22. package/dist/combat/LoadoutBuilder.js.map +1 -0
  23. package/dist/combat/MonsterAbilityData.d.ts +97 -0
  24. package/dist/combat/MonsterAbilityData.d.ts.map +1 -0
  25. package/dist/combat/MonsterAbilityData.js +94 -0
  26. package/dist/combat/MonsterAbilityData.js.map +1 -0
  27. package/dist/combat/WeaponSelector.d.ts +47 -0
  28. package/dist/combat/WeaponSelector.d.ts.map +1 -0
  29. package/dist/combat/WeaponSelector.js +180 -0
  30. package/dist/combat/WeaponSelector.js.map +1 -0
  31. package/dist/combat/index.d.ts +9 -0
  32. package/dist/combat/index.d.ts.map +1 -0
  33. package/dist/combat/index.js +6 -0
  34. package/dist/combat/index.js.map +1 -0
  35. package/dist/conditions/ConditionBank.d.ts +179 -0
  36. package/dist/conditions/ConditionBank.d.ts.map +1 -0
  37. package/dist/conditions/ConditionBank.js +220 -0
  38. package/dist/conditions/ConditionBank.js.map +1 -0
  39. package/dist/conditions/index.d.ts +3 -0
  40. package/dist/conditions/index.d.ts.map +1 -0
  41. package/dist/conditions/index.js +3 -0
  42. package/dist/conditions/index.js.map +1 -0
  43. package/dist/config/createDefaultAIConfig.d.ts +25 -0
  44. package/dist/config/createDefaultAIConfig.d.ts.map +1 -0
  45. package/dist/config/createDefaultAIConfig.js +147 -0
  46. package/dist/config/createDefaultAIConfig.js.map +1 -0
  47. package/dist/config/index.d.ts +2 -0
  48. package/dist/config/index.d.ts.map +1 -0
  49. package/dist/config/index.js +3 -0
  50. package/dist/config/index.js.map +1 -0
  51. package/dist/cover/CoverAccessAdapter.d.ts +61 -0
  52. package/dist/cover/CoverAccessAdapter.d.ts.map +1 -0
  53. package/dist/cover/CoverAccessAdapter.js +74 -0
  54. package/dist/cover/CoverAccessAdapter.js.map +1 -0
  55. package/dist/cover/CoverEvaluators.d.ts +43 -0
  56. package/dist/cover/CoverEvaluators.d.ts.map +1 -0
  57. package/dist/cover/CoverEvaluators.js +193 -0
  58. package/dist/cover/CoverEvaluators.js.map +1 -0
  59. package/dist/cover/CoverLockRegistry.d.ts +50 -0
  60. package/dist/cover/CoverLockRegistry.d.ts.map +1 -0
  61. package/dist/cover/CoverLockRegistry.js +164 -0
  62. package/dist/cover/CoverLockRegistry.js.map +1 -0
  63. package/dist/cover/CoverRecommender.d.ts +32 -0
  64. package/dist/cover/CoverRecommender.d.ts.map +1 -0
  65. package/dist/cover/CoverRecommender.js +45 -0
  66. package/dist/cover/CoverRecommender.js.map +1 -0
  67. package/dist/cover/CoverRegistry.d.ts +97 -0
  68. package/dist/cover/CoverRegistry.d.ts.map +1 -0
  69. package/dist/cover/CoverRegistry.js +223 -0
  70. package/dist/cover/CoverRegistry.js.map +1 -0
  71. package/dist/cover/ICoverEvaluator.d.ts +15 -0
  72. package/dist/cover/ICoverEvaluator.d.ts.map +1 -0
  73. package/dist/cover/ICoverEvaluator.js +4 -0
  74. package/dist/cover/ICoverEvaluator.js.map +1 -0
  75. package/dist/cover/ICoverLockConfig.d.ts +83 -0
  76. package/dist/cover/ICoverLockConfig.d.ts.map +1 -0
  77. package/dist/cover/ICoverLockConfig.js +21 -0
  78. package/dist/cover/ICoverLockConfig.js.map +1 -0
  79. package/dist/cover/LoopholeGenerator.d.ts +44 -0
  80. package/dist/cover/LoopholeGenerator.d.ts.map +1 -0
  81. package/dist/cover/LoopholeGenerator.js +96 -0
  82. package/dist/cover/LoopholeGenerator.js.map +1 -0
  83. package/dist/cover/index.d.ts +11 -0
  84. package/dist/cover/index.d.ts.map +1 -0
  85. package/dist/cover/index.js +8 -0
  86. package/dist/cover/index.js.map +1 -0
  87. package/dist/goap/EvadeHazardAction.d.ts +34 -0
  88. package/dist/goap/EvadeHazardAction.d.ts.map +1 -0
  89. package/dist/goap/EvadeHazardAction.js +48 -0
  90. package/dist/goap/EvadeHazardAction.js.map +1 -0
  91. package/dist/goap/GOAPController.d.ts +114 -0
  92. package/dist/goap/GOAPController.d.ts.map +1 -0
  93. package/dist/goap/GOAPController.js +191 -0
  94. package/dist/goap/GOAPController.js.map +1 -0
  95. package/dist/goap/GoalSelector.d.ts +40 -0
  96. package/dist/goap/GoalSelector.d.ts.map +1 -0
  97. package/dist/goap/GoalSelector.js +115 -0
  98. package/dist/goap/GoalSelector.js.map +1 -0
  99. package/dist/goap/IHazardZoneAccess.d.ts +16 -0
  100. package/dist/goap/IHazardZoneAccess.d.ts.map +1 -0
  101. package/dist/goap/IHazardZoneAccess.js +2 -0
  102. package/dist/goap/IHazardZoneAccess.js.map +1 -0
  103. package/dist/goap/WorldStateBuilder.d.ts +27 -0
  104. package/dist/goap/WorldStateBuilder.d.ts.map +1 -0
  105. package/dist/goap/WorldStateBuilder.js +51 -0
  106. package/dist/goap/WorldStateBuilder.js.map +1 -0
  107. package/dist/goap/index.d.ts +9 -0
  108. package/dist/goap/index.d.ts.map +1 -0
  109. package/dist/goap/index.js +6 -0
  110. package/dist/goap/index.js.map +1 -0
  111. package/dist/index.d.ts +16 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +18 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/navigation/PathSmoother.d.ts +29 -0
  116. package/dist/navigation/PathSmoother.d.ts.map +1 -0
  117. package/dist/navigation/PathSmoother.js +172 -0
  118. package/dist/navigation/PathSmoother.js.map +1 -0
  119. package/dist/navigation/RestrictedZoneManager.d.ts +83 -0
  120. package/dist/navigation/RestrictedZoneManager.d.ts.map +1 -0
  121. package/dist/navigation/RestrictedZoneManager.js +179 -0
  122. package/dist/navigation/RestrictedZoneManager.js.map +1 -0
  123. package/dist/navigation/SmoothPathFollower.d.ts +55 -0
  124. package/dist/navigation/SmoothPathFollower.d.ts.map +1 -0
  125. package/dist/navigation/SmoothPathFollower.js +132 -0
  126. package/dist/navigation/SmoothPathFollower.js.map +1 -0
  127. package/dist/navigation/SteeringBehaviors.d.ts +123 -0
  128. package/dist/navigation/SteeringBehaviors.d.ts.map +1 -0
  129. package/dist/navigation/SteeringBehaviors.js +211 -0
  130. package/dist/navigation/SteeringBehaviors.js.map +1 -0
  131. package/dist/navigation/index.d.ts +7 -0
  132. package/dist/navigation/index.d.ts.map +1 -0
  133. package/dist/navigation/index.js +6 -0
  134. package/dist/navigation/index.js.map +1 -0
  135. package/dist/perception/NPCSensors.d.ts +129 -0
  136. package/dist/perception/NPCSensors.d.ts.map +1 -0
  137. package/dist/perception/NPCSensors.js +147 -0
  138. package/dist/perception/NPCSensors.js.map +1 -0
  139. package/dist/perception/PerceptionQuery.d.ts +65 -0
  140. package/dist/perception/PerceptionQuery.d.ts.map +1 -0
  141. package/dist/perception/PerceptionQuery.js +199 -0
  142. package/dist/perception/PerceptionQuery.js.map +1 -0
  143. package/dist/perception/index.d.ts +4 -0
  144. package/dist/perception/index.d.ts.map +1 -0
  145. package/dist/perception/index.js +4 -0
  146. package/dist/perception/index.js.map +1 -0
  147. package/dist/plugin/AIPlugin.d.ts +71 -0
  148. package/dist/plugin/AIPlugin.d.ts.map +1 -0
  149. package/dist/plugin/AIPlugin.js +134 -0
  150. package/dist/plugin/AIPlugin.js.map +1 -0
  151. package/dist/plugin/index.d.ts +3 -0
  152. package/dist/plugin/index.d.ts.map +1 -0
  153. package/dist/plugin/index.js +3 -0
  154. package/dist/plugin/index.js.map +1 -0
  155. package/dist/ports/AIPorts.d.ts +13 -0
  156. package/dist/ports/AIPorts.d.ts.map +1 -0
  157. package/dist/ports/AIPorts.js +14 -0
  158. package/dist/ports/AIPorts.js.map +1 -0
  159. package/dist/ports/ICoverPointSource.d.ts +27 -0
  160. package/dist/ports/ICoverPointSource.d.ts.map +1 -0
  161. package/dist/ports/ICoverPointSource.js +4 -0
  162. package/dist/ports/ICoverPointSource.js.map +1 -0
  163. package/dist/ports/IPerceptionProvider.d.ts +42 -0
  164. package/dist/ports/IPerceptionProvider.d.ts.map +1 -0
  165. package/dist/ports/IPerceptionProvider.js +4 -0
  166. package/dist/ports/IPerceptionProvider.js.map +1 -0
  167. package/dist/ports/index.d.ts +4 -0
  168. package/dist/ports/index.d.ts.map +1 -0
  169. package/dist/ports/index.js +3 -0
  170. package/dist/ports/index.js.map +1 -0
  171. package/dist/sound/VocalizationTypes.d.ts +57 -0
  172. package/dist/sound/VocalizationTypes.d.ts.map +1 -0
  173. package/dist/sound/VocalizationTypes.js +87 -0
  174. package/dist/sound/VocalizationTypes.js.map +1 -0
  175. package/dist/sound/index.d.ts +3 -0
  176. package/dist/sound/index.d.ts.map +1 -0
  177. package/dist/sound/index.js +3 -0
  178. package/dist/sound/index.js.map +1 -0
  179. package/dist/squad/SquadSharedTarget.d.ts +137 -0
  180. package/dist/squad/SquadSharedTarget.d.ts.map +1 -0
  181. package/dist/squad/SquadSharedTarget.js +145 -0
  182. package/dist/squad/SquadSharedTarget.js.map +1 -0
  183. package/dist/squad/SquadTactics.d.ts +63 -0
  184. package/dist/squad/SquadTactics.d.ts.map +1 -0
  185. package/dist/squad/SquadTactics.js +76 -0
  186. package/dist/squad/SquadTactics.js.map +1 -0
  187. package/dist/squad/index.d.ts +5 -0
  188. package/dist/squad/index.d.ts.map +1 -0
  189. package/dist/squad/index.js +4 -0
  190. package/dist/squad/index.js.map +1 -0
  191. package/dist/states/INPCContext.d.ts +550 -0
  192. package/dist/states/INPCContext.d.ts.map +1 -0
  193. package/dist/states/INPCContext.js +17 -0
  194. package/dist/states/INPCContext.js.map +1 -0
  195. package/dist/states/INPCOnlineState.d.ts +202 -0
  196. package/dist/states/INPCOnlineState.d.ts.map +1 -0
  197. package/dist/states/INPCOnlineState.js +9 -0
  198. package/dist/states/INPCOnlineState.js.map +1 -0
  199. package/dist/states/IOnlineStateHandler.d.ts +58 -0
  200. package/dist/states/IOnlineStateHandler.d.ts.map +1 -0
  201. package/dist/states/IOnlineStateHandler.js +13 -0
  202. package/dist/states/IOnlineStateHandler.js.map +1 -0
  203. package/dist/states/IStateConfig.d.ts +272 -0
  204. package/dist/states/IStateConfig.d.ts.map +1 -0
  205. package/dist/states/IStateConfig.js +100 -0
  206. package/dist/states/IStateConfig.js.map +1 -0
  207. package/dist/states/IStateTransitionMap.d.ts +89 -0
  208. package/dist/states/IStateTransitionMap.d.ts.map +1 -0
  209. package/dist/states/IStateTransitionMap.js +75 -0
  210. package/dist/states/IStateTransitionMap.js.map +1 -0
  211. package/dist/states/NPCOnlineState.d.ts +19 -0
  212. package/dist/states/NPCOnlineState.d.ts.map +1 -0
  213. package/dist/states/NPCOnlineState.js +75 -0
  214. package/dist/states/NPCOnlineState.js.map +1 -0
  215. package/dist/states/NPCPerception.d.ts +108 -0
  216. package/dist/states/NPCPerception.d.ts.map +1 -0
  217. package/dist/states/NPCPerception.js +122 -0
  218. package/dist/states/NPCPerception.js.map +1 -0
  219. package/dist/states/OnlineAIDriver.d.ts +64 -0
  220. package/dist/states/OnlineAIDriver.d.ts.map +1 -0
  221. package/dist/states/OnlineAIDriver.js +171 -0
  222. package/dist/states/OnlineAIDriver.js.map +1 -0
  223. package/dist/states/OnlineStateRegistryBuilder.d.ts +115 -0
  224. package/dist/states/OnlineStateRegistryBuilder.d.ts.map +1 -0
  225. package/dist/states/OnlineStateRegistryBuilder.js +184 -0
  226. package/dist/states/OnlineStateRegistryBuilder.js.map +1 -0
  227. package/dist/states/StateHandlerMap.d.ts +52 -0
  228. package/dist/states/StateHandlerMap.d.ts.map +1 -0
  229. package/dist/states/StateHandlerMap.js +88 -0
  230. package/dist/states/StateHandlerMap.js.map +1 -0
  231. package/dist/states/eat-corpse/EatCorpseState.d.ts +32 -0
  232. package/dist/states/eat-corpse/EatCorpseState.d.ts.map +1 -0
  233. package/dist/states/eat-corpse/EatCorpseState.js +126 -0
  234. package/dist/states/eat-corpse/EatCorpseState.js.map +1 -0
  235. package/dist/states/eat-corpse/EatCorpseTransitionGuard.d.ts +34 -0
  236. package/dist/states/eat-corpse/EatCorpseTransitionGuard.d.ts.map +1 -0
  237. package/dist/states/eat-corpse/EatCorpseTransitionGuard.js +82 -0
  238. package/dist/states/eat-corpse/EatCorpseTransitionGuard.js.map +1 -0
  239. package/dist/states/eat-corpse/ICorpseSource.d.ts +87 -0
  240. package/dist/states/eat-corpse/ICorpseSource.d.ts.map +1 -0
  241. package/dist/states/eat-corpse/ICorpseSource.js +5 -0
  242. package/dist/states/eat-corpse/ICorpseSource.js.map +1 -0
  243. package/dist/states/eat-corpse/IEatCorpseConfig.d.ts +75 -0
  244. package/dist/states/eat-corpse/IEatCorpseConfig.d.ts.map +1 -0
  245. package/dist/states/eat-corpse/IEatCorpseConfig.js +23 -0
  246. package/dist/states/eat-corpse/IEatCorpseConfig.js.map +1 -0
  247. package/dist/states/eat-corpse/IEatCorpsePhase.d.ts +23 -0
  248. package/dist/states/eat-corpse/IEatCorpsePhase.d.ts.map +1 -0
  249. package/dist/states/eat-corpse/IEatCorpsePhase.js +5 -0
  250. package/dist/states/eat-corpse/IEatCorpsePhase.js.map +1 -0
  251. package/dist/states/eat-corpse/index.d.ts +7 -0
  252. package/dist/states/eat-corpse/index.d.ts.map +1 -0
  253. package/dist/states/eat-corpse/index.js +11 -0
  254. package/dist/states/eat-corpse/index.js.map +1 -0
  255. package/dist/states/handlers/AlertState.d.ts +18 -0
  256. package/dist/states/handlers/AlertState.d.ts.map +1 -0
  257. package/dist/states/handlers/AlertState.js +104 -0
  258. package/dist/states/handlers/AlertState.js.map +1 -0
  259. package/dist/states/handlers/CampState.d.ts +18 -0
  260. package/dist/states/handlers/CampState.d.ts.map +1 -0
  261. package/dist/states/handlers/CampState.js +94 -0
  262. package/dist/states/handlers/CampState.js.map +1 -0
  263. package/dist/states/handlers/ChargeState.d.ts +18 -0
  264. package/dist/states/handlers/ChargeState.d.ts.map +1 -0
  265. package/dist/states/handlers/ChargeState.js +103 -0
  266. package/dist/states/handlers/ChargeState.js.map +1 -0
  267. package/dist/states/handlers/CombatState.d.ts +19 -0
  268. package/dist/states/handlers/CombatState.d.ts.map +1 -0
  269. package/dist/states/handlers/CombatState.js +137 -0
  270. package/dist/states/handlers/CombatState.js.map +1 -0
  271. package/dist/states/handlers/CombatTransitionHandler.d.ts +34 -0
  272. package/dist/states/handlers/CombatTransitionHandler.d.ts.map +1 -0
  273. package/dist/states/handlers/CombatTransitionHandler.js +137 -0
  274. package/dist/states/handlers/CombatTransitionHandler.js.map +1 -0
  275. package/dist/states/handlers/DeadState.d.ts +16 -0
  276. package/dist/states/handlers/DeadState.d.ts.map +1 -0
  277. package/dist/states/handlers/DeadState.js +35 -0
  278. package/dist/states/handlers/DeadState.js.map +1 -0
  279. package/dist/states/handlers/EvadeGrenadeState.d.ts +23 -0
  280. package/dist/states/handlers/EvadeGrenadeState.d.ts.map +1 -0
  281. package/dist/states/handlers/EvadeGrenadeState.js +93 -0
  282. package/dist/states/handlers/EvadeGrenadeState.js.map +1 -0
  283. package/dist/states/handlers/FleeState.d.ts +18 -0
  284. package/dist/states/handlers/FleeState.d.ts.map +1 -0
  285. package/dist/states/handlers/FleeState.js +61 -0
  286. package/dist/states/handlers/FleeState.js.map +1 -0
  287. package/dist/states/handlers/GrenadeState.d.ts +18 -0
  288. package/dist/states/handlers/GrenadeState.d.ts.map +1 -0
  289. package/dist/states/handlers/GrenadeState.js +61 -0
  290. package/dist/states/handlers/GrenadeState.js.map +1 -0
  291. package/dist/states/handlers/HelpWoundedState.d.ts +27 -0
  292. package/dist/states/handlers/HelpWoundedState.d.ts.map +1 -0
  293. package/dist/states/handlers/HelpWoundedState.js +131 -0
  294. package/dist/states/handlers/HelpWoundedState.js.map +1 -0
  295. package/dist/states/handlers/IdleState.d.ts +18 -0
  296. package/dist/states/handlers/IdleState.d.ts.map +1 -0
  297. package/dist/states/handlers/IdleState.js +127 -0
  298. package/dist/states/handlers/IdleState.js.map +1 -0
  299. package/dist/states/handlers/InvestigateState.d.ts +27 -0
  300. package/dist/states/handlers/InvestigateState.d.ts.map +1 -0
  301. package/dist/states/handlers/InvestigateState.js +145 -0
  302. package/dist/states/handlers/InvestigateState.js.map +1 -0
  303. package/dist/states/handlers/KillWoundedState.d.ts +27 -0
  304. package/dist/states/handlers/KillWoundedState.d.ts.map +1 -0
  305. package/dist/states/handlers/KillWoundedState.js +147 -0
  306. package/dist/states/handlers/KillWoundedState.js.map +1 -0
  307. package/dist/states/handlers/LeapState.d.ts +18 -0
  308. package/dist/states/handlers/LeapState.d.ts.map +1 -0
  309. package/dist/states/handlers/LeapState.js +115 -0
  310. package/dist/states/handlers/LeapState.js.map +1 -0
  311. package/dist/states/handlers/MonsterCombatController.d.ts +55 -0
  312. package/dist/states/handlers/MonsterCombatController.d.ts.map +1 -0
  313. package/dist/states/handlers/MonsterCombatController.js +152 -0
  314. package/dist/states/handlers/MonsterCombatController.js.map +1 -0
  315. package/dist/states/handlers/PatrolState.d.ts +18 -0
  316. package/dist/states/handlers/PatrolState.d.ts.map +1 -0
  317. package/dist/states/handlers/PatrolState.js +137 -0
  318. package/dist/states/handlers/PatrolState.js.map +1 -0
  319. package/dist/states/handlers/PsiAttackState.d.ts +18 -0
  320. package/dist/states/handlers/PsiAttackState.d.ts.map +1 -0
  321. package/dist/states/handlers/PsiAttackState.js +101 -0
  322. package/dist/states/handlers/PsiAttackState.js.map +1 -0
  323. package/dist/states/handlers/RetreatState.d.ts +18 -0
  324. package/dist/states/handlers/RetreatState.d.ts.map +1 -0
  325. package/dist/states/handlers/RetreatState.js +131 -0
  326. package/dist/states/handlers/RetreatState.js.map +1 -0
  327. package/dist/states/handlers/SearchState.d.ts +18 -0
  328. package/dist/states/handlers/SearchState.d.ts.map +1 -0
  329. package/dist/states/handlers/SearchState.js +64 -0
  330. package/dist/states/handlers/SearchState.js.map +1 -0
  331. package/dist/states/handlers/SleepState.d.ts +18 -0
  332. package/dist/states/handlers/SleepState.d.ts.map +1 -0
  333. package/dist/states/handlers/SleepState.js +94 -0
  334. package/dist/states/handlers/SleepState.js.map +1 -0
  335. package/dist/states/handlers/StalkState.d.ts +18 -0
  336. package/dist/states/handlers/StalkState.d.ts.map +1 -0
  337. package/dist/states/handlers/StalkState.js +82 -0
  338. package/dist/states/handlers/StalkState.js.map +1 -0
  339. package/dist/states/handlers/TakeCoverState.d.ts +18 -0
  340. package/dist/states/handlers/TakeCoverState.d.ts.map +1 -0
  341. package/dist/states/handlers/TakeCoverState.js +208 -0
  342. package/dist/states/handlers/TakeCoverState.js.map +1 -0
  343. package/dist/states/handlers/WoundedState.d.ts +18 -0
  344. package/dist/states/handlers/WoundedState.d.ts.map +1 -0
  345. package/dist/states/handlers/WoundedState.js +71 -0
  346. package/dist/states/handlers/WoundedState.js.map +1 -0
  347. package/dist/states/handlers/_utils.d.ts +55 -0
  348. package/dist/states/handlers/_utils.d.ts.map +1 -0
  349. package/dist/states/handlers/_utils.js +88 -0
  350. package/dist/states/handlers/_utils.js.map +1 -0
  351. package/dist/states/handlers/index.d.ts +25 -0
  352. package/dist/states/handlers/index.d.ts.map +1 -0
  353. package/dist/states/handlers/index.js +28 -0
  354. package/dist/states/handlers/index.js.map +1 -0
  355. package/dist/states/index.d.ts +17 -0
  356. package/dist/states/index.d.ts.map +1 -0
  357. package/dist/states/index.js +12 -0
  358. package/dist/states/index.js.map +1 -0
  359. package/dist/states/pack/IPackAccess.d.ts +46 -0
  360. package/dist/states/pack/IPackAccess.d.ts.map +1 -0
  361. package/dist/states/pack/IPackAccess.js +8 -0
  362. package/dist/states/pack/IPackAccess.js.map +1 -0
  363. package/dist/suspicion/SuspicionAccumulator.d.ts +166 -0
  364. package/dist/suspicion/SuspicionAccumulator.d.ts.map +1 -0
  365. package/dist/suspicion/SuspicionAccumulator.js +191 -0
  366. package/dist/suspicion/SuspicionAccumulator.js.map +1 -0
  367. package/dist/suspicion/index.d.ts +3 -0
  368. package/dist/suspicion/index.d.ts.map +1 -0
  369. package/dist/suspicion/index.js +2 -0
  370. package/dist/suspicion/index.js.map +1 -0
  371. package/dist/types/IAnimationTypes.d.ts +28 -0
  372. package/dist/types/IAnimationTypes.d.ts.map +1 -0
  373. package/dist/types/IAnimationTypes.js +17 -0
  374. package/dist/types/IAnimationTypes.js.map +1 -0
  375. package/dist/types/ICoverPoint.d.ts +76 -0
  376. package/dist/types/ICoverPoint.d.ts.map +1 -0
  377. package/dist/types/ICoverPoint.js +21 -0
  378. package/dist/types/ICoverPoint.js.map +1 -0
  379. package/dist/types/IOnlineAIConfig.d.ts +150 -0
  380. package/dist/types/IOnlineAIConfig.d.ts.map +1 -0
  381. package/dist/types/IOnlineAIConfig.js +5 -0
  382. package/dist/types/IOnlineAIConfig.js.map +1 -0
  383. package/dist/types/IPerceptionTypes.d.ts +94 -0
  384. package/dist/types/IPerceptionTypes.d.ts.map +1 -0
  385. package/dist/types/IPerceptionTypes.js +37 -0
  386. package/dist/types/IPerceptionTypes.js.map +1 -0
  387. package/dist/types/IWeaponTypes.d.ts +56 -0
  388. package/dist/types/IWeaponTypes.d.ts.map +1 -0
  389. package/dist/types/IWeaponTypes.js +15 -0
  390. package/dist/types/IWeaponTypes.js.map +1 -0
  391. package/dist/types/index.d.ts +10 -0
  392. package/dist/types/index.d.ts.map +1 -0
  393. package/dist/types/index.js +5 -0
  394. package/dist/types/index.js.map +1 -0
  395. package/package.json +123 -0
@@ -0,0 +1,61 @@
1
+ import type { ICoverAccess } from '../states/INPCContext';
2
+ import { CoverRegistry } from './CoverRegistry';
3
+ import type { ICoverLockRegistry } from './ICoverLockConfig';
4
+ /**
5
+ * Per-NPC cover access adapter.
6
+ *
7
+ * Bridges the generic `ICoverAccess` contract used by state handlers with
8
+ * the concrete `CoverRegistry` + `CoverLockRegistry` SDK classes.
9
+ *
10
+ * Responsibilities:
11
+ * - Translates the flat `(x, y, enemyX, enemyY)` API to the typed
12
+ * `CoverRegistry.findCover(type, pos, enemies, npcId)` call.
13
+ * - Stores the `ICoverPoint.id` of the last successful `findCover` result
14
+ * so that `lockLastFound()` can acquire the TTL lock without requiring
15
+ * the caller to manage point IDs.
16
+ *
17
+ * **Create one adapter per NPC** via `AIPlugin.createCoverAccess(npcId)`.
18
+ * The adapter is stateful (tracks `_lastFoundId`) and must not be shared
19
+ * across different NPC entities.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // Phaser bridge setup (PhaserNPCContext):
24
+ * const coverAccess = aiPlugin.createCoverAccess(npcId);
25
+ * // Then expose via INPCContext.cover = coverAccess
26
+ * ```
27
+ */
28
+ export declare class CoverAccessAdapter implements ICoverAccess {
29
+ private readonly _registry;
30
+ private readonly _lockRegistry;
31
+ private readonly _npcId;
32
+ private _lastFoundId;
33
+ /**
34
+ * @param _registry - Shared cover registry (scene-level singleton).
35
+ * @param _lockRegistry - Optional TTL lock registry. When null, locking
36
+ * is skipped and `lockLastFound` returns true.
37
+ * @param _npcId - The NPC this adapter serves. Used as the requester
38
+ * ID in `findCover` occupancy filtering.
39
+ */
40
+ constructor(_registry: CoverRegistry, _lockRegistry: ICoverLockRegistry | null, _npcId: string);
41
+ findCover(x: number, y: number, enemyX: number, enemyY: number, type?: string): {
42
+ x: number;
43
+ y: number;
44
+ } | null;
45
+ /**
46
+ * Acquire a TTL lock on the most recently returned cover point.
47
+ *
48
+ * Returns `true` (vacuous success) if:
49
+ * - No cover point has been found yet (`findCover` was not called or returned null).
50
+ * - No lock registry was provided at construction time.
51
+ *
52
+ * Returns `false` if the point is already locked at capacity by other NPCs.
53
+ */
54
+ lockLastFound(npcId: string, ttlMs?: number): boolean;
55
+ /**
56
+ * Release all TTL locks held by the given NPC in the lock registry.
57
+ * No-op if no lock registry was provided at construction time.
58
+ */
59
+ unlockAll(npcId: string): void;
60
+ }
61
+ //# sourceMappingURL=CoverAccessAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverAccessAdapter.d.ts","sourceRoot":"","sources":["../../src/cover/CoverAccessAdapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IAWnD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAZzB,OAAO,CAAC,YAAY,CAAuB;IAE3C;;;;;;OAMG;gBAEgB,SAAS,EAAE,aAAa,EACxB,aAAa,EAAE,kBAAkB,GAAG,IAAI,EACxC,MAAM,EAAE,MAAM;IAOjC,SAAS,CACP,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACZ;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAelC;;;;;;;;OAQG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IASrD;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAG/B"}
@@ -0,0 +1,74 @@
1
+ // cover/CoverAccessAdapter.ts
2
+ // SDK-provided implementation of ICoverAccess that bridges CoverRegistry
3
+ // with an optional CoverLockRegistry.
4
+ import { CoverType as CoverTypeConst } from '../types/ICoverPoint';
5
+ /**
6
+ * Per-NPC cover access adapter.
7
+ *
8
+ * Bridges the generic `ICoverAccess` contract used by state handlers with
9
+ * the concrete `CoverRegistry` + `CoverLockRegistry` SDK classes.
10
+ *
11
+ * Responsibilities:
12
+ * - Translates the flat `(x, y, enemyX, enemyY)` API to the typed
13
+ * `CoverRegistry.findCover(type, pos, enemies, npcId)` call.
14
+ * - Stores the `ICoverPoint.id` of the last successful `findCover` result
15
+ * so that `lockLastFound()` can acquire the TTL lock without requiring
16
+ * the caller to manage point IDs.
17
+ *
18
+ * **Create one adapter per NPC** via `AIPlugin.createCoverAccess(npcId)`.
19
+ * The adapter is stateful (tracks `_lastFoundId`) and must not be shared
20
+ * across different NPC entities.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * // Phaser bridge setup (PhaserNPCContext):
25
+ * const coverAccess = aiPlugin.createCoverAccess(npcId);
26
+ * // Then expose via INPCContext.cover = coverAccess
27
+ * ```
28
+ */
29
+ export class CoverAccessAdapter {
30
+ /**
31
+ * @param _registry - Shared cover registry (scene-level singleton).
32
+ * @param _lockRegistry - Optional TTL lock registry. When null, locking
33
+ * is skipped and `lockLastFound` returns true.
34
+ * @param _npcId - The NPC this adapter serves. Used as the requester
35
+ * ID in `findCover` occupancy filtering.
36
+ */
37
+ constructor(_registry, _lockRegistry, _npcId) {
38
+ this._registry = _registry;
39
+ this._lockRegistry = _lockRegistry;
40
+ this._npcId = _npcId;
41
+ this._lastFoundId = null;
42
+ }
43
+ // -------------------------------------------------------------------------
44
+ // ICoverAccess
45
+ // -------------------------------------------------------------------------
46
+ findCover(x, y, enemyX, enemyY, type) {
47
+ const coverType = type ?? CoverTypeConst.BALANCED;
48
+ const point = this._registry.findCover(coverType, { x, y }, [{ x: enemyX, y: enemyY }], this._npcId);
49
+ this._lastFoundId = point?.id ?? null;
50
+ return point !== null ? { x: point.x, y: point.y } : null;
51
+ }
52
+ /**
53
+ * Acquire a TTL lock on the most recently returned cover point.
54
+ *
55
+ * Returns `true` (vacuous success) if:
56
+ * - No cover point has been found yet (`findCover` was not called or returned null).
57
+ * - No lock registry was provided at construction time.
58
+ *
59
+ * Returns `false` if the point is already locked at capacity by other NPCs.
60
+ */
61
+ lockLastFound(npcId, ttlMs) {
62
+ if (this._lockRegistry === null || this._lastFoundId === null)
63
+ return true;
64
+ return this._lockRegistry.tryLock(this._lastFoundId, npcId, ttlMs !== undefined ? { ttlMs } : undefined);
65
+ }
66
+ /**
67
+ * Release all TTL locks held by the given NPC in the lock registry.
68
+ * No-op if no lock registry was provided at construction time.
69
+ */
70
+ unlockAll(npcId) {
71
+ this._lockRegistry?.unlockAll(npcId);
72
+ }
73
+ }
74
+ //# sourceMappingURL=CoverAccessAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverAccessAdapter.js","sourceRoot":"","sources":["../../src/cover/CoverAccessAdapter.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,yEAAyE;AACzE,sCAAsC;AAItC,OAAO,EAAE,SAAS,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAInE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,kBAAkB;IAG7B;;;;;;OAMG;IACH,YACmB,SAAwB,EACxB,aAAwC,EACxC,MAAc;QAFd,cAAS,GAAT,SAAS,CAAe;QACxB,kBAAa,GAAb,aAAa,CAA2B;QACxC,WAAM,GAAN,MAAM,CAAQ;QAZzB,iBAAY,GAAkB,IAAI,CAAC;IAaxC,CAAC;IAEJ,4EAA4E;IAC5E,eAAe;IACf,4EAA4E;IAE5E,SAAS,CACP,CAAS,EACT,CAAS,EACT,MAAc,EACd,MAAc,EACd,IAAa;QAEb,MAAM,SAAS,GAAe,IAAkB,IAAI,cAAc,CAAC,QAAQ,CAAC;QAE5E,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CACpC,SAAS,EACT,EAAE,CAAC,EAAE,CAAC,EAAE,EACR,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAC1B,IAAI,CAAC,MAAM,CACZ,CAAC;QAEF,IAAI,CAAC,YAAY,GAAG,KAAK,EAAE,EAAE,IAAI,IAAI,CAAC;QAEtC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,CAAC;IAED;;;;;;;;OAQG;IACH,aAAa,CAAC,KAAa,EAAE,KAAc;QACzC,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC3E,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAC/B,IAAI,CAAC,YAAY,EACjB,KAAK,EACL,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAC5C,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,43 @@
1
+ import type { ICoverPoint, ICoverEvalContext } from '../types/ICoverPoint';
2
+ import { CoverType } from '../types/ICoverPoint';
3
+ import type { ICoverEvaluator } from './ICoverEvaluator';
4
+ import type { ICoverConfig } from '../types/IOnlineAIConfig';
5
+ export declare class CloseCoverEvaluator implements ICoverEvaluator {
6
+ readonly type: "close";
7
+ private readonly maxRange;
8
+ constructor(config: ICoverConfig);
9
+ evaluate(point: ICoverPoint, context: ICoverEvalContext): number;
10
+ }
11
+ export declare class FarCoverEvaluator implements ICoverEvaluator {
12
+ readonly type: "far";
13
+ private readonly maxRange;
14
+ constructor(config: ICoverConfig);
15
+ evaluate(point: ICoverPoint, context: ICoverEvalContext): number;
16
+ }
17
+ export declare class BalancedCoverEvaluator implements ICoverEvaluator {
18
+ readonly type: "balanced";
19
+ evaluate(point: ICoverPoint, context: ICoverEvalContext): number;
20
+ }
21
+ export declare class AmbushCoverEvaluator implements ICoverEvaluator {
22
+ readonly type: "ambush";
23
+ private readonly minAngle;
24
+ private readonly maxAngle;
25
+ private readonly minDist;
26
+ private readonly maxDist;
27
+ constructor(config: ICoverConfig);
28
+ evaluate(point: ICoverPoint, context: ICoverEvalContext): number;
29
+ }
30
+ export declare class SafeCoverEvaluator implements ICoverEvaluator {
31
+ readonly type: "safe";
32
+ evaluate(point: ICoverPoint, context: ICoverEvalContext): number;
33
+ }
34
+ /**
35
+ * Create a complete set of cover evaluators keyed by CoverType.
36
+ *
37
+ * @param config - Cover subsystem configuration.
38
+ * @returns Map of CoverType → ICoverEvaluator.
39
+ */
40
+ export declare function createCoverEvaluators(config: ICoverConfig): ReadonlyMap<CoverType, ICoverEvaluator>;
41
+ /** @deprecated Use BalancedCoverEvaluator */
42
+ export declare const BestCoverEvaluator: typeof BalancedCoverEvaluator;
43
+ //# sourceMappingURL=CoverEvaluators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverEvaluators.d.ts","sourceRoot":"","sources":["../../src/cover/CoverEvaluators.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAkB,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA6B7D,qBAAa,mBAAoB,YAAW,eAAe;IACzD,QAAQ,CAAC,IAAI,UAAmB;IAEhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,EAAE,YAAY;IAIhC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM;CAajE;AAMD,qBAAa,iBAAkB,YAAW,eAAe;IACvD,QAAQ,CAAC,IAAI,QAAiB;IAE9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,EAAE,YAAY;IAIhC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM;CAajE;AAMD,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,QAAQ,CAAC,IAAI,aAAsB;IAEnC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM;CAwBjE;AAMD,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,QAAQ,CAAC,IAAI,WAAoB;IAEjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,YAAY;IAOhC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM;CAsCjE;AAMD,qBAAa,kBAAmB,YAAW,eAAe;IACxD,QAAQ,CAAC,IAAI,SAAkB;IAE/B,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM;CAkBjE;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,GACnB,WAAW,CAAC,SAAS,EAAE,eAAe,CAAC,CAQzC;AAED,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB,+BAAyB,CAAC"}
@@ -0,0 +1,193 @@
1
+ // cover/CoverEvaluators.ts
2
+ // Five tactical cover evaluators implementing the Strategy pattern.
3
+ //
4
+ // Each evaluator scores a cover point on [0, 1] for a specific tactical
5
+ // priority. They are pure functions — no side effects, no state,
6
+ // fully deterministic given the same inputs.
7
+ import { distanceSq } from '@alife-sdk/core';
8
+ import { CoverType } from '../types/ICoverPoint';
9
+ // ---------------------------------------------------------------------------
10
+ // Shared geometry helpers
11
+ // ---------------------------------------------------------------------------
12
+ function averageEnemyPosition(enemies) {
13
+ if (enemies.length === 0)
14
+ return { x: 0, y: 0 };
15
+ let sx = 0;
16
+ let sy = 0;
17
+ for (const e of enemies) {
18
+ sx += e.x;
19
+ sy += e.y;
20
+ }
21
+ return { x: sx / enemies.length, y: sy / enemies.length };
22
+ }
23
+ function angleBetween(from, to) {
24
+ return Math.atan2(to.y - from.y, to.x - from.x);
25
+ }
26
+ function clamp01(value) {
27
+ return value < 0 ? 0 : value > 1 ? 1 : value;
28
+ }
29
+ // ---------------------------------------------------------------------------
30
+ // CLOSE — nearest cover, quick retreat under fire
31
+ // ---------------------------------------------------------------------------
32
+ export class CloseCoverEvaluator {
33
+ constructor(config) {
34
+ this.type = CoverType.CLOSE;
35
+ this.maxRange = config.closeMaxRange;
36
+ }
37
+ evaluate(point, context) {
38
+ const dSq = distanceSq(context.npcPosition, point);
39
+ const dist = Math.sqrt(dSq);
40
+ const ratio = dist / this.maxRange;
41
+ // Beyond max range: score drops linearly to 0 at 2x max range.
42
+ if (ratio > 1.0) {
43
+ return clamp01(1.0 - (ratio - 1.0));
44
+ }
45
+ // Within range: closer is better. Score 1.0 at distance 0.
46
+ return 1.0 - ratio;
47
+ }
48
+ }
49
+ // ---------------------------------------------------------------------------
50
+ // FAR — maximize distance from enemies, strategic retreat
51
+ // ---------------------------------------------------------------------------
52
+ export class FarCoverEvaluator {
53
+ constructor(config) {
54
+ this.type = CoverType.FAR;
55
+ this.maxRange = config.farMaxRange;
56
+ }
57
+ evaluate(point, context) {
58
+ if (context.enemies.length === 0)
59
+ return 0.5;
60
+ // Score based on average distance to all enemies.
61
+ let totalDist = 0;
62
+ for (const enemy of context.enemies) {
63
+ totalDist += Math.sqrt(distanceSq(point, enemy));
64
+ }
65
+ const avgDist = totalDist / context.enemies.length;
66
+ // Normalize: 1.0 at maxRange or beyond, 0 at distance 0.
67
+ return clamp01(avgDist / this.maxRange);
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // BALANCED — balanced three-factor weighted score
72
+ // ---------------------------------------------------------------------------
73
+ export class BalancedCoverEvaluator {
74
+ constructor() {
75
+ this.type = CoverType.BALANCED;
76
+ }
77
+ evaluate(point, context) {
78
+ if (context.enemies.length === 0)
79
+ return 0.5;
80
+ const centroid = averageEnemyPosition(context.enemies);
81
+ const coverDist = Math.sqrt(distanceSq(context.npcPosition, point));
82
+ const enemyDist = Math.sqrt(distanceSq(point, centroid));
83
+ // Factor 1: proximity to NPC (closer = better, max 30 points).
84
+ const proximityScore = clamp01(1.0 - coverDist / 400) * 30;
85
+ // Factor 2: distance from enemies (farther = safer, max 30 points).
86
+ const safetyScore = clamp01(enemyDist / 600) * 30;
87
+ // Factor 3: angle quality — cover between NPC and enemy is ideal (max 30 points).
88
+ const npcToEnemy = angleBetween(context.npcPosition, centroid);
89
+ const npcToCover = angleBetween(context.npcPosition, point);
90
+ let angleDelta = Math.abs(npcToEnemy - npcToCover);
91
+ if (angleDelta > Math.PI)
92
+ angleDelta = 2 * Math.PI - angleDelta;
93
+ // Small angle difference means cover is roughly toward/away from enemy.
94
+ const angleScore = clamp01(1.0 - angleDelta / Math.PI) * 30;
95
+ // Normalize to [0, 1] (max raw = 90).
96
+ return (proximityScore + safetyScore + angleScore) / 90;
97
+ }
98
+ }
99
+ // ---------------------------------------------------------------------------
100
+ // AMBUSH — flanking position, offensive posture
101
+ // ---------------------------------------------------------------------------
102
+ export class AmbushCoverEvaluator {
103
+ constructor(config) {
104
+ this.type = CoverType.AMBUSH;
105
+ this.minAngle = config.ambushMinAngle;
106
+ this.maxAngle = config.ambushMaxAngle;
107
+ this.minDist = config.ambushMinDist;
108
+ this.maxDist = config.ambushMaxDist;
109
+ }
110
+ evaluate(point, context) {
111
+ if (context.enemies.length === 0)
112
+ return 0;
113
+ const centroid = averageEnemyPosition(context.enemies);
114
+ // Distance from cover to enemy centroid.
115
+ const dist = Math.sqrt(distanceSq(point, centroid));
116
+ if (dist < this.minDist || dist > this.maxDist) {
117
+ // Outside ambush distance band — poor score.
118
+ return clamp01(0.2 - Math.abs(dist - (this.minDist + this.maxDist) / 2) / this.maxDist);
119
+ }
120
+ // Flanking angle: angle between (enemy→NPC) and (enemy→cover).
121
+ const enemyToNpc = angleBetween(centroid, context.npcPosition);
122
+ const enemyToCover = angleBetween(centroid, point);
123
+ let flankAngle = Math.abs(enemyToNpc - enemyToCover);
124
+ if (flankAngle > Math.PI)
125
+ flankAngle = 2 * Math.PI - flankAngle;
126
+ // Best flanking is between minAngle and maxAngle (roughly 60°-120°).
127
+ if (flankAngle >= this.minAngle && flankAngle <= this.maxAngle) {
128
+ // Perfect flanking band — high score.
129
+ if (this.maxDist === this.minDist)
130
+ return 0.85;
131
+ const distScore = 1.0 - Math.abs(dist - (this.minDist + this.maxDist) / 2) / (this.maxDist - this.minDist);
132
+ return clamp01(0.7 + distScore * 0.3);
133
+ }
134
+ // Outside flanking band — reduced score based on deviation.
135
+ let deviation;
136
+ if (flankAngle < this.minAngle) {
137
+ if (this.minAngle <= 0)
138
+ return 0;
139
+ deviation = (this.minAngle - flankAngle) / this.minAngle;
140
+ }
141
+ else {
142
+ if (Math.PI - this.maxAngle <= 0)
143
+ return 0;
144
+ deviation = (flankAngle - this.maxAngle) / (Math.PI - this.maxAngle);
145
+ }
146
+ return clamp01(0.5 * (1.0 - deviation));
147
+ }
148
+ }
149
+ // ---------------------------------------------------------------------------
150
+ // SAFE — minimize aggregate threat exposure
151
+ // ---------------------------------------------------------------------------
152
+ export class SafeCoverEvaluator {
153
+ constructor() {
154
+ this.type = CoverType.SAFE;
155
+ }
156
+ evaluate(point, context) {
157
+ if (context.enemies.length === 0)
158
+ return 1.0;
159
+ // Aggregate threat: sum of inverse squared distances to each enemy.
160
+ // Lower threat = safer = higher score.
161
+ let threatSum = 0;
162
+ for (const enemy of context.enemies) {
163
+ const dSq = distanceSq(point, enemy);
164
+ // Avoid division by zero; minimum distance of 1px.
165
+ threatSum += 1.0 / Math.max(1, dSq);
166
+ }
167
+ // Normalize threat to [0, 1]. Empirically, threat rarely exceeds 0.01
168
+ // for reasonable distances (>10px per enemy).
169
+ const normalizedThreat = clamp01(threatSum * 5000);
170
+ return 1.0 - normalizedThreat;
171
+ }
172
+ }
173
+ // ---------------------------------------------------------------------------
174
+ // Factory — create all evaluators from config
175
+ // ---------------------------------------------------------------------------
176
+ /**
177
+ * Create a complete set of cover evaluators keyed by CoverType.
178
+ *
179
+ * @param config - Cover subsystem configuration.
180
+ * @returns Map of CoverType → ICoverEvaluator.
181
+ */
182
+ export function createCoverEvaluators(config) {
183
+ const map = new Map();
184
+ map.set(CoverType.CLOSE, new CloseCoverEvaluator(config));
185
+ map.set(CoverType.FAR, new FarCoverEvaluator(config));
186
+ map.set(CoverType.BALANCED, new BalancedCoverEvaluator());
187
+ map.set(CoverType.AMBUSH, new AmbushCoverEvaluator(config));
188
+ map.set(CoverType.SAFE, new SafeCoverEvaluator());
189
+ return map;
190
+ }
191
+ /** @deprecated Use BalancedCoverEvaluator */
192
+ export const BestCoverEvaluator = BalancedCoverEvaluator;
193
+ //# sourceMappingURL=CoverEvaluators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverEvaluators.js","sourceRoot":"","sources":["../../src/cover/CoverEvaluators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { ICoverLockConfig, ICoverLockRegistry } from './ICoverLockConfig';
2
+ /**
3
+ * TTL-based reservation system for cover points.
4
+ *
5
+ * Locks are stored per point-ID in `Map<string, PointEntry>`.
6
+ * Expired entries are pruned lazily (inline on tryLock/isAvailable) and
7
+ * periodically via auto-purge at `autoPurgeInterval` cadence.
8
+ *
9
+ * Memory at scale: 200 NPCs × 1 lock each ≈ 200 Map entries, ~20KB.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const locks = new CoverLockRegistry(() => Date.now());
14
+ *
15
+ * // In TakeCoverState.enter():
16
+ * const ok = locks.tryLock('cover_0012', npcId);
17
+ *
18
+ * // In TakeCoverState.exit():
19
+ * locks.unlockAll(npcId);
20
+ * ```
21
+ */
22
+ export declare class CoverLockRegistry implements ICoverLockRegistry {
23
+ private readonly _points;
24
+ private readonly config;
25
+ private readonly timeFn;
26
+ private _checkCounter;
27
+ /**
28
+ * @param timeFn - Monotonically non-decreasing time source (returns ms).
29
+ * Must not return negative or wildly non-monotonic values.
30
+ * @param config - Optional config overrides (TTL, capacity, auto-purge rate).
31
+ */
32
+ constructor(timeFn: () => number, config?: Partial<ICoverLockConfig>);
33
+ tryLock(pointId: string, npcId: string, options?: {
34
+ ttlMs?: number;
35
+ capacity?: number;
36
+ }): boolean;
37
+ unlock(pointId: string, npcId: string): void;
38
+ unlockAll(npcId: string): void;
39
+ isAvailable(pointId: string, npcId: string): boolean;
40
+ purgeExpired(): number;
41
+ clear(): void;
42
+ /**
43
+ * Approximate count of points with at least one lock entry.
44
+ * May include points whose locks have all expired but not yet been purged.
45
+ * Call `purgeExpired()` first for an exact count.
46
+ */
47
+ get lockedPointCount(): number;
48
+ private _maybeAutoPurge;
49
+ }
50
+ //# sourceMappingURL=CoverLockRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverLockRegistry.d.ts","sourceRoot":"","sources":["../../src/cover/CoverLockRegistry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AA4B/E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,aAAa,CAAK;IAE1B;;;;OAIG;gBACS,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;IASpE,OAAO,CACL,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,OAAO;IAkDV,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAU5C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAc9B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAkBpD,YAAY,IAAI,MAAM;IAoBtB,KAAK,IAAI,IAAI;IAKb;;;;OAIG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAMD,OAAO,CAAC,eAAe;CAOxB"}
@@ -0,0 +1,164 @@
1
+ // cover/CoverLockRegistry.ts
2
+ // TTL-based cover point reservation system.
3
+ import { createDefaultCoverLockConfig } from './ICoverLockConfig';
4
+ // ---------------------------------------------------------------------------
5
+ // CoverLockRegistry
6
+ // ---------------------------------------------------------------------------
7
+ /**
8
+ * TTL-based reservation system for cover points.
9
+ *
10
+ * Locks are stored per point-ID in `Map<string, PointEntry>`.
11
+ * Expired entries are pruned lazily (inline on tryLock/isAvailable) and
12
+ * periodically via auto-purge at `autoPurgeInterval` cadence.
13
+ *
14
+ * Memory at scale: 200 NPCs × 1 lock each ≈ 200 Map entries, ~20KB.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const locks = new CoverLockRegistry(() => Date.now());
19
+ *
20
+ * // In TakeCoverState.enter():
21
+ * const ok = locks.tryLock('cover_0012', npcId);
22
+ *
23
+ * // In TakeCoverState.exit():
24
+ * locks.unlockAll(npcId);
25
+ * ```
26
+ */
27
+ export class CoverLockRegistry {
28
+ /**
29
+ * @param timeFn - Monotonically non-decreasing time source (returns ms).
30
+ * Must not return negative or wildly non-monotonic values.
31
+ * @param config - Optional config overrides (TTL, capacity, auto-purge rate).
32
+ */
33
+ constructor(timeFn, config) {
34
+ this._points = new Map();
35
+ this._checkCounter = 0;
36
+ this.timeFn = timeFn;
37
+ this.config = createDefaultCoverLockConfig(config);
38
+ }
39
+ // -------------------------------------------------------------------------
40
+ // ICoverLockRegistry
41
+ // -------------------------------------------------------------------------
42
+ tryLock(pointId, npcId, options) {
43
+ this._maybeAutoPurge();
44
+ const now = this.timeFn();
45
+ const ttl = options?.ttlMs ?? this.config.defaultTtlMs;
46
+ const capacity = options?.capacity ?? this.config.defaultCapacity;
47
+ const expiresAt = now + ttl;
48
+ const entry = this._points.get(pointId);
49
+ if (entry === undefined) {
50
+ this._points.set(pointId, { capacity, locks: [{ npcId, expiresAt }] });
51
+ return true;
52
+ }
53
+ // Promote capacity if this call requests higher capacity for this point.
54
+ if (capacity > entry.capacity) {
55
+ entry.capacity = capacity;
56
+ }
57
+ // Prune expired entries inline (arrays are typically size 1-3).
58
+ let activeCount = 0;
59
+ let ownIdx = -1;
60
+ for (let i = 0; i < entry.locks.length; i++) {
61
+ const lock = entry.locks[i];
62
+ if (lock.expiresAt <= now)
63
+ continue; // expired
64
+ if (lock.npcId === npcId) {
65
+ ownIdx = i;
66
+ }
67
+ else {
68
+ activeCount++;
69
+ }
70
+ }
71
+ if (ownIdx !== -1) {
72
+ // Refresh TTL for the NPC's existing lock.
73
+ entry.locks[ownIdx].expiresAt = expiresAt;
74
+ // Compact out expired entries.
75
+ entry.locks = entry.locks.filter((l) => l.expiresAt > now);
76
+ return true;
77
+ }
78
+ if (activeCount >= entry.capacity) {
79
+ entry.locks = entry.locks.filter((l) => l.expiresAt > now);
80
+ return false;
81
+ }
82
+ // Compact + add new lock.
83
+ entry.locks = entry.locks.filter((l) => l.expiresAt > now);
84
+ entry.locks.push({ npcId, expiresAt });
85
+ return true;
86
+ }
87
+ unlock(pointId, npcId) {
88
+ const entry = this._points.get(pointId);
89
+ if (entry === undefined)
90
+ return;
91
+ entry.locks = entry.locks.filter((l) => l.npcId !== npcId);
92
+ if (entry.locks.length === 0) {
93
+ this._points.delete(pointId);
94
+ }
95
+ }
96
+ unlockAll(npcId) {
97
+ // Collect points to delete after iteration to avoid mutation-during-iteration.
98
+ const toDelete = [];
99
+ for (const [pointId, entry] of this._points) {
100
+ entry.locks = entry.locks.filter((l) => l.npcId !== npcId);
101
+ if (entry.locks.length === 0) {
102
+ toDelete.push(pointId);
103
+ }
104
+ }
105
+ for (const id of toDelete)
106
+ this._points.delete(id);
107
+ }
108
+ isAvailable(pointId, npcId) {
109
+ this._maybeAutoPurge();
110
+ const entry = this._points.get(pointId);
111
+ if (entry === undefined)
112
+ return true;
113
+ const now = this.timeFn();
114
+ let activeCount = 0;
115
+ for (const lock of entry.locks) {
116
+ if (lock.expiresAt <= now)
117
+ continue;
118
+ if (lock.npcId === npcId)
119
+ return true; // own lock — always available
120
+ activeCount++;
121
+ }
122
+ return activeCount < entry.capacity;
123
+ }
124
+ purgeExpired() {
125
+ const now = this.timeFn();
126
+ let purged = 0;
127
+ const toDelete = [];
128
+ for (const [pointId, entry] of this._points) {
129
+ const before = entry.locks.length;
130
+ entry.locks = entry.locks.filter((l) => l.expiresAt > now);
131
+ purged += before - entry.locks.length;
132
+ if (entry.locks.length === 0) {
133
+ toDelete.push(pointId);
134
+ }
135
+ }
136
+ for (const id of toDelete)
137
+ this._points.delete(id);
138
+ return purged;
139
+ }
140
+ clear() {
141
+ this._points.clear();
142
+ this._checkCounter = 0;
143
+ }
144
+ /**
145
+ * Approximate count of points with at least one lock entry.
146
+ * May include points whose locks have all expired but not yet been purged.
147
+ * Call `purgeExpired()` first for an exact count.
148
+ */
149
+ get lockedPointCount() {
150
+ return this._points.size;
151
+ }
152
+ // -------------------------------------------------------------------------
153
+ // Internal
154
+ // -------------------------------------------------------------------------
155
+ _maybeAutoPurge() {
156
+ if (this.config.autoPurgeInterval <= 0)
157
+ return;
158
+ if (++this._checkCounter >= this.config.autoPurgeInterval) {
159
+ this._checkCounter = 0;
160
+ this.purgeExpired();
161
+ }
162
+ }
163
+ }
164
+ //# sourceMappingURL=CoverLockRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverLockRegistry.js","sourceRoot":"","sources":["../../src/cover/CoverLockRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { CoverType } from '../types/ICoverPoint';
2
+ import type { ICoverConfig } from '../types/IOnlineAIConfig';
3
+ /**
4
+ * Tactical context for cover type recommendation.
5
+ */
6
+ export interface ICoverSituation {
7
+ /** Current HP / max HP in range [0, 1]. */
8
+ readonly hpRatio: number;
9
+ /** Current morale in range [-1, 1]. */
10
+ readonly morale: number;
11
+ /** Number of known active enemies. */
12
+ readonly enemyCount: number;
13
+ /** Whether the NPC has usable ammunition. */
14
+ readonly hasAmmo: boolean;
15
+ }
16
+ /**
17
+ * Recommend the best CoverType for a given tactical situation.
18
+ *
19
+ * Decision tree (priority order):
20
+ * 1. No ammo → SAFE (no point being offensive).
21
+ * 2. Critical HP → CLOSE (need cover NOW, closest available).
22
+ * 3. Demoralized → FAR (distance = psychological safety).
23
+ * 4. Outnumbered → SAFE (minimize exposure to multiple threats).
24
+ * 5. Healthy + few enemies → AMBUSH (take offensive position).
25
+ * 6. Default → BALANCED (balanced approach).
26
+ *
27
+ * @param situation - Tactical context describing the NPC's state.
28
+ * @param config - Cover configuration for threshold values.
29
+ * @returns The recommended CoverType.
30
+ */
31
+ export declare function recommendCoverType(situation: ICoverSituation, config: ICoverConfig): CoverType;
32
+ //# sourceMappingURL=CoverRecommender.d.ts.map