@rpgm-tools/neo-angband-core 0.10.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 (1183) hide show
  1. package/LICENSE.md +43 -0
  2. package/README.md +80 -0
  3. package/dist/agent/act.d.ts +22 -0
  4. package/dist/agent/act.d.ts.map +1 -0
  5. package/dist/agent/act.js +88 -0
  6. package/dist/agent/act.js.map +1 -0
  7. package/dist/agent/controller.d.ts +34 -0
  8. package/dist/agent/controller.d.ts.map +1 -0
  9. package/dist/agent/controller.js +90 -0
  10. package/dist/agent/controller.js.map +1 -0
  11. package/dist/agent/events.d.ts +27 -0
  12. package/dist/agent/events.d.ts.map +1 -0
  13. package/dist/agent/events.js +31 -0
  14. package/dist/agent/events.js.map +1 -0
  15. package/dist/agent/index.d.ts +17 -0
  16. package/dist/agent/index.d.ts.map +1 -0
  17. package/dist/agent/index.js +15 -0
  18. package/dist/agent/index.js.map +1 -0
  19. package/dist/agent/perceive.d.ts +21 -0
  20. package/dist/agent/perceive.d.ts.map +1 -0
  21. package/dist/agent/perceive.js +386 -0
  22. package/dist/agent/perceive.js.map +1 -0
  23. package/dist/agent/types.d.ts +436 -0
  24. package/dist/agent/types.d.ts.map +1 -0
  25. package/dist/agent/types.js +63 -0
  26. package/dist/agent/types.js.map +1 -0
  27. package/dist/bitflag.d.ts +199 -0
  28. package/dist/bitflag.d.ts.map +1 -0
  29. package/dist/bitflag.js +478 -0
  30. package/dist/bitflag.js.map +1 -0
  31. package/dist/cmd.d.ts +164 -0
  32. package/dist/cmd.d.ts.map +1 -0
  33. package/dist/cmd.js +350 -0
  34. package/dist/cmd.js.map +1 -0
  35. package/dist/color.d.ts +104 -0
  36. package/dist/color.d.ts.map +1 -0
  37. package/dist/color.js +240 -0
  38. package/dist/color.js.map +1 -0
  39. package/dist/combat/brand-slay.d.ts +119 -0
  40. package/dist/combat/brand-slay.d.ts.map +1 -0
  41. package/dist/combat/brand-slay.js +264 -0
  42. package/dist/combat/brand-slay.js.map +1 -0
  43. package/dist/combat/hit.d.ts +198 -0
  44. package/dist/combat/hit.d.ts.map +1 -0
  45. package/dist/combat/hit.js +310 -0
  46. package/dist/combat/hit.js.map +1 -0
  47. package/dist/combat/index.d.ts +15 -0
  48. package/dist/combat/index.d.ts.map +1 -0
  49. package/dist/combat/index.js +15 -0
  50. package/dist/combat/index.js.map +1 -0
  51. package/dist/combat/melee.d.ts +261 -0
  52. package/dist/combat/melee.d.ts.map +1 -0
  53. package/dist/combat/melee.js +402 -0
  54. package/dist/combat/melee.js.map +1 -0
  55. package/dist/combat/mon-melee.d.ts +233 -0
  56. package/dist/combat/mon-melee.d.ts.map +1 -0
  57. package/dist/combat/mon-melee.js +883 -0
  58. package/dist/combat/mon-melee.js.map +1 -0
  59. package/dist/combat/ranged.d.ts +89 -0
  60. package/dist/combat/ranged.d.ts.map +1 -0
  61. package/dist/combat/ranged.js +253 -0
  62. package/dist/combat/ranged.js.map +1 -0
  63. package/dist/constants.d.ts +134 -0
  64. package/dist/constants.d.ts.map +1 -0
  65. package/dist/constants.js +171 -0
  66. package/dist/constants.js.map +1 -0
  67. package/dist/dice.d.ts +91 -0
  68. package/dist/dice.d.ts.map +1 -0
  69. package/dist/dice.js +424 -0
  70. package/dist/dice.js.map +1 -0
  71. package/dist/effects/effect-choice.d.ts +15 -0
  72. package/dist/effects/effect-choice.d.ts.map +1 -0
  73. package/dist/effects/effect-choice.js +18 -0
  74. package/dist/effects/effect-choice.js.map +1 -0
  75. package/dist/effects/effect-info.d.ts +124 -0
  76. package/dist/effects/effect-info.d.ts.map +1 -0
  77. package/dist/effects/effect-info.js +706 -0
  78. package/dist/effects/effect-info.js.map +1 -0
  79. package/dist/effects/effect.d.ts +165 -0
  80. package/dist/effects/effect.d.ts.map +1 -0
  81. package/dist/effects/effect.js +452 -0
  82. package/dist/effects/effect.js.map +1 -0
  83. package/dist/effects/handlers.d.ts +70 -0
  84. package/dist/effects/handlers.d.ts.map +1 -0
  85. package/dist/effects/handlers.js +394 -0
  86. package/dist/effects/handlers.js.map +1 -0
  87. package/dist/effects/interpreter.d.ts +291 -0
  88. package/dist/effects/interpreter.d.ts.map +1 -0
  89. package/dist/effects/interpreter.js +325 -0
  90. package/dist/effects/interpreter.js.map +1 -0
  91. package/dist/events.d.ts +188 -0
  92. package/dist/events.d.ts.map +1 -0
  93. package/dist/events.js +138 -0
  94. package/dist/events.js.map +1 -0
  95. package/dist/expression.d.ts +83 -0
  96. package/dist/expression.d.ts.map +1 -0
  97. package/dist/expression.js +333 -0
  98. package/dist/expression.js.map +1 -0
  99. package/dist/game/cave-cmd.d.ts +195 -0
  100. package/dist/game/cave-cmd.d.ts.map +1 -0
  101. package/dist/game/cave-cmd.js +968 -0
  102. package/dist/game/cave-cmd.js.map +1 -0
  103. package/dist/game/char-sheet.d.ts +189 -0
  104. package/dist/game/char-sheet.d.ts.map +1 -0
  105. package/dist/game/char-sheet.js +381 -0
  106. package/dist/game/char-sheet.js.map +1 -0
  107. package/dist/game/chest.d.ts +94 -0
  108. package/dist/game/chest.d.ts.map +1 -0
  109. package/dist/game/chest.js +267 -0
  110. package/dist/game/chest.js.map +1 -0
  111. package/dist/game/context.d.ts +970 -0
  112. package/dist/game/context.d.ts.map +1 -0
  113. package/dist/game/context.js +353 -0
  114. package/dist/game/context.js.map +1 -0
  115. package/dist/game/curse-tick.d.ts +35 -0
  116. package/dist/game/curse-tick.d.ts.map +1 -0
  117. package/dist/game/curse-tick.js +100 -0
  118. package/dist/game/curse-tick.js.map +1 -0
  119. package/dist/game/describe.d.ts +20 -0
  120. package/dist/game/describe.d.ts.map +1 -0
  121. package/dist/game/describe.js +45 -0
  122. package/dist/game/describe.js.map +1 -0
  123. package/dist/game/display.d.ts +196 -0
  124. package/dist/game/display.d.ts.map +1 -0
  125. package/dist/game/display.js +684 -0
  126. package/dist/game/display.js.map +1 -0
  127. package/dist/game/dump-level.d.ts +37 -0
  128. package/dist/game/dump-level.d.ts.map +1 -0
  129. package/dist/game/dump-level.js +110 -0
  130. package/dist/game/dump-level.js.map +1 -0
  131. package/dist/game/effect-attack.d.ts +36 -0
  132. package/dist/game/effect-attack.d.ts.map +1 -0
  133. package/dist/game/effect-attack.js +694 -0
  134. package/dist/game/effect-attack.js.map +1 -0
  135. package/dist/game/effect-detect.d.ts +34 -0
  136. package/dist/game/effect-detect.d.ts.map +1 -0
  137. package/dist/game/effect-detect.js +456 -0
  138. package/dist/game/effect-detect.js.map +1 -0
  139. package/dist/game/effect-env.d.ts +77 -0
  140. package/dist/game/effect-env.d.ts.map +1 -0
  141. package/dist/game/effect-env.js +166 -0
  142. package/dist/game/effect-env.js.map +1 -0
  143. package/dist/game/effect-game-env.d.ts +76 -0
  144. package/dist/game/effect-game-env.d.ts.map +1 -0
  145. package/dist/game/effect-game-env.js +23 -0
  146. package/dist/game/effect-game-env.js.map +1 -0
  147. package/dist/game/effect-general.d.ts +98 -0
  148. package/dist/game/effect-general.d.ts.map +1 -0
  149. package/dist/game/effect-general.js +914 -0
  150. package/dist/game/effect-general.js.map +1 -0
  151. package/dist/game/effect-item.d.ts +124 -0
  152. package/dist/game/effect-item.d.ts.map +1 -0
  153. package/dist/game/effect-item.js +789 -0
  154. package/dist/game/effect-item.js.map +1 -0
  155. package/dist/game/effect-melee.d.ts +43 -0
  156. package/dist/game/effect-melee.d.ts.map +1 -0
  157. package/dist/game/effect-melee.js +477 -0
  158. package/dist/game/effect-melee.js.map +1 -0
  159. package/dist/game/effect-mon-origin.d.ts +67 -0
  160. package/dist/game/effect-mon-origin.d.ts.map +1 -0
  161. package/dist/game/effect-mon-origin.js +164 -0
  162. package/dist/game/effect-mon-origin.js.map +1 -0
  163. package/dist/game/effect-monster.d.ts +29 -0
  164. package/dist/game/effect-monster.d.ts.map +1 -0
  165. package/dist/game/effect-monster.js +281 -0
  166. package/dist/game/effect-monster.js.map +1 -0
  167. package/dist/game/effect-summon.d.ts +37 -0
  168. package/dist/game/effect-summon.d.ts.map +1 -0
  169. package/dist/game/effect-summon.js +113 -0
  170. package/dist/game/effect-summon.js.map +1 -0
  171. package/dist/game/effect-teleport.d.ts +130 -0
  172. package/dist/game/effect-teleport.d.ts.map +1 -0
  173. package/dist/game/effect-teleport.js +529 -0
  174. package/dist/game/effect-teleport.js.map +1 -0
  175. package/dist/game/effect-terrain.d.ts +91 -0
  176. package/dist/game/effect-terrain.d.ts.map +1 -0
  177. package/dist/game/effect-terrain.js +812 -0
  178. package/dist/game/effect-terrain.js.map +1 -0
  179. package/dist/game/energy.d.ts +45 -0
  180. package/dist/game/energy.d.ts.map +1 -0
  181. package/dist/game/energy.js +51 -0
  182. package/dist/game/energy.js.map +1 -0
  183. package/dist/game/equip-cmp.d.ts +138 -0
  184. package/dist/game/equip-cmp.d.ts.map +1 -0
  185. package/dist/game/equip-cmp.js +363 -0
  186. package/dist/game/equip-cmp.js.map +1 -0
  187. package/dist/game/floor.d.ts +182 -0
  188. package/dist/game/floor.d.ts.map +1 -0
  189. package/dist/game/floor.js +435 -0
  190. package/dist/game/floor.js.map +1 -0
  191. package/dist/game/gear.d.ts +408 -0
  192. package/dist/game/gear.d.ts.map +1 -0
  193. package/dist/game/gear.js +1037 -0
  194. package/dist/game/gear.js.map +1 -0
  195. package/dist/game/harness.d.ts +61 -0
  196. package/dist/game/harness.d.ts.map +1 -0
  197. package/dist/game/harness.js +198 -0
  198. package/dist/game/harness.js.map +1 -0
  199. package/dist/game/history.d.ts +49 -0
  200. package/dist/game/history.d.ts.map +1 -0
  201. package/dist/game/history.js +55 -0
  202. package/dist/game/history.js.map +1 -0
  203. package/dist/game/ignore-cmd.d.ts +42 -0
  204. package/dist/game/ignore-cmd.d.ts.map +1 -0
  205. package/dist/game/ignore-cmd.js +59 -0
  206. package/dist/game/ignore-cmd.js.map +1 -0
  207. package/dist/game/inscription-confirm.d.ts +80 -0
  208. package/dist/game/inscription-confirm.d.ts.map +1 -0
  209. package/dist/game/inscription-confirm.js +95 -0
  210. package/dist/game/inscription-confirm.js.map +1 -0
  211. package/dist/game/known.d.ts +297 -0
  212. package/dist/game/known.d.ts.map +1 -0
  213. package/dist/game/known.js +849 -0
  214. package/dist/game/known.js.map +1 -0
  215. package/dist/game/loop.d.ts +139 -0
  216. package/dist/game/loop.d.ts.map +1 -0
  217. package/dist/game/loop.js +631 -0
  218. package/dist/game/loop.js.map +1 -0
  219. package/dist/game/lore-color.d.ts +25 -0
  220. package/dist/game/lore-color.d.ts.map +1 -0
  221. package/dist/game/lore-color.js +95 -0
  222. package/dist/game/lore-color.js.map +1 -0
  223. package/dist/game/mon-cast.d.ts +150 -0
  224. package/dist/game/mon-cast.d.ts.map +1 -0
  225. package/dist/game/mon-cast.js +301 -0
  226. package/dist/game/mon-cast.js.map +1 -0
  227. package/dist/game/mon-cmd.d.ts +51 -0
  228. package/dist/game/mon-cmd.d.ts.map +1 -0
  229. package/dist/game/mon-cmd.js +670 -0
  230. package/dist/game/mon-cmd.js.map +1 -0
  231. package/dist/game/mon-death.d.ts +143 -0
  232. package/dist/game/mon-death.d.ts.map +1 -0
  233. package/dist/game/mon-death.js +328 -0
  234. package/dist/game/mon-death.js.map +1 -0
  235. package/dist/game/mon-group.d.ts +81 -0
  236. package/dist/game/mon-group.d.ts.map +1 -0
  237. package/dist/game/mon-group.js +323 -0
  238. package/dist/game/mon-group.js.map +1 -0
  239. package/dist/game/mon-list.d.ts +85 -0
  240. package/dist/game/mon-list.d.ts.map +1 -0
  241. package/dist/game/mon-list.js +154 -0
  242. package/dist/game/mon-list.js.map +1 -0
  243. package/dist/game/mon-message.d.ts +100 -0
  244. package/dist/game/mon-message.d.ts.map +1 -0
  245. package/dist/game/mon-message.js +336 -0
  246. package/dist/game/mon-message.js.map +1 -0
  247. package/dist/game/mon-place.d.ts +226 -0
  248. package/dist/game/mon-place.d.ts.map +1 -0
  249. package/dist/game/mon-place.js +642 -0
  250. package/dist/game/mon-place.js.map +1 -0
  251. package/dist/game/mon-ranged.d.ts +87 -0
  252. package/dist/game/mon-ranged.d.ts.map +1 -0
  253. package/dist/game/mon-ranged.js +353 -0
  254. package/dist/game/mon-ranged.js.map +1 -0
  255. package/dist/game/mon-shape.d.ts +43 -0
  256. package/dist/game/mon-shape.d.ts.map +1 -0
  257. package/dist/game/mon-shape.js +115 -0
  258. package/dist/game/mon-shape.js.map +1 -0
  259. package/dist/game/mon-side.d.ts +63 -0
  260. package/dist/game/mon-side.d.ts.map +1 -0
  261. package/dist/game/mon-side.js +403 -0
  262. package/dist/game/mon-side.js.map +1 -0
  263. package/dist/game/monster-turn.d.ts +195 -0
  264. package/dist/game/monster-turn.d.ts.map +1 -0
  265. package/dist/game/monster-turn.js +1560 -0
  266. package/dist/game/monster-turn.js.map +1 -0
  267. package/dist/game/obj-cmd.d.ts +453 -0
  268. package/dist/game/obj-cmd.d.ts.map +1 -0
  269. package/dist/game/obj-cmd.js +1530 -0
  270. package/dist/game/obj-cmd.js.map +1 -0
  271. package/dist/game/obj-list.d.ts +92 -0
  272. package/dist/game/obj-list.d.ts.map +1 -0
  273. package/dist/game/obj-list.js +251 -0
  274. package/dist/game/obj-list.js.map +1 -0
  275. package/dist/game/object-inspect.d.ts +37 -0
  276. package/dist/game/object-inspect.d.ts.map +1 -0
  277. package/dist/game/object-inspect.js +106 -0
  278. package/dist/game/object-inspect.js.map +1 -0
  279. package/dist/game/pickup.d.ts +126 -0
  280. package/dist/game/pickup.d.ts.map +1 -0
  281. package/dist/game/pickup.js +367 -0
  282. package/dist/game/pickup.js.map +1 -0
  283. package/dist/game/player-path.d.ts +133 -0
  284. package/dist/game/player-path.d.ts.map +1 -0
  285. package/dist/game/player-path.js +1268 -0
  286. package/dist/game/player-path.js.map +1 -0
  287. package/dist/game/player-side.d.ts +59 -0
  288. package/dist/game/player-side.d.ts.map +1 -0
  289. package/dist/game/player-side.js +506 -0
  290. package/dist/game/player-side.js.map +1 -0
  291. package/dist/game/player-turn.d.ts +161 -0
  292. package/dist/game/player-turn.d.ts.map +1 -0
  293. package/dist/game/player-turn.js +739 -0
  294. package/dist/game/player-turn.js.map +1 -0
  295. package/dist/game/project-cast.d.ts +268 -0
  296. package/dist/game/project-cast.d.ts.map +1 -0
  297. package/dist/game/project-cast.js +496 -0
  298. package/dist/game/project-cast.js.map +1 -0
  299. package/dist/game/project-feat.d.ts +47 -0
  300. package/dist/game/project-feat.d.ts.map +1 -0
  301. package/dist/game/project-feat.js +350 -0
  302. package/dist/game/project-feat.js.map +1 -0
  303. package/dist/game/project-monster.d.ts +106 -0
  304. package/dist/game/project-monster.d.ts.map +1 -0
  305. package/dist/game/project-monster.js +272 -0
  306. package/dist/game/project-monster.js.map +1 -0
  307. package/dist/game/project-obj.d.ts +60 -0
  308. package/dist/game/project-obj.d.ts.map +1 -0
  309. package/dist/game/project-obj.js +245 -0
  310. package/dist/game/project-obj.js.map +1 -0
  311. package/dist/game/project-player.d.ts +120 -0
  312. package/dist/game/project-player.d.ts.map +1 -0
  313. package/dist/game/project-player.js +108 -0
  314. package/dist/game/project-player.js.map +1 -0
  315. package/dist/game/quest.d.ts +101 -0
  316. package/dist/game/quest.d.ts.map +1 -0
  317. package/dist/game/quest.js +192 -0
  318. package/dist/game/quest.js.map +1 -0
  319. package/dist/game/ranged-cmd.d.ts +32 -0
  320. package/dist/game/ranged-cmd.d.ts.map +1 -0
  321. package/dist/game/ranged-cmd.js +372 -0
  322. package/dist/game/ranged-cmd.js.map +1 -0
  323. package/dist/game/scheduler.d.ts +47 -0
  324. package/dist/game/scheduler.d.ts.map +1 -0
  325. package/dist/game/scheduler.js +141 -0
  326. package/dist/game/scheduler.js.map +1 -0
  327. package/dist/game/spell-cmd.d.ts +104 -0
  328. package/dist/game/spell-cmd.d.ts.map +1 -0
  329. package/dist/game/spell-cmd.js +320 -0
  330. package/dist/game/spell-cmd.js.map +1 -0
  331. package/dist/game/spoil.d.ts +28 -0
  332. package/dist/game/spoil.d.ts.map +1 -0
  333. package/dist/game/spoil.js +435 -0
  334. package/dist/game/spoil.js.map +1 -0
  335. package/dist/game/steal.d.ts +35 -0
  336. package/dist/game/steal.d.ts.map +1 -0
  337. package/dist/game/steal.js +145 -0
  338. package/dist/game/steal.js.map +1 -0
  339. package/dist/game/take-hit-hooks.d.ts +52 -0
  340. package/dist/game/take-hit-hooks.d.ts.map +1 -0
  341. package/dist/game/take-hit-hooks.js +127 -0
  342. package/dist/game/take-hit-hooks.js.map +1 -0
  343. package/dist/game/target-loop.d.ts +119 -0
  344. package/dist/game/target-loop.d.ts.map +1 -0
  345. package/dist/game/target-loop.js +408 -0
  346. package/dist/game/target-loop.js.map +1 -0
  347. package/dist/game/target.d.ts +133 -0
  348. package/dist/game/target.d.ts.map +1 -0
  349. package/dist/game/target.js +353 -0
  350. package/dist/game/target.js.map +1 -0
  351. package/dist/game/thrust.d.ts +37 -0
  352. package/dist/game/thrust.d.ts.map +1 -0
  353. package/dist/game/thrust.js +155 -0
  354. package/dist/game/thrust.js.map +1 -0
  355. package/dist/game/trap.d.ts +218 -0
  356. package/dist/game/trap.d.ts.map +1 -0
  357. package/dist/game/trap.js +618 -0
  358. package/dist/game/trap.js.map +1 -0
  359. package/dist/game/ui-entry.d.ts +282 -0
  360. package/dist/game/ui-entry.d.ts.map +1 -0
  361. package/dist/game/ui-entry.js +1838 -0
  362. package/dist/game/ui-entry.js.map +1 -0
  363. package/dist/game/wizard.d.ts +654 -0
  364. package/dist/game/wizard.d.ts.map +1 -0
  365. package/dist/game/wizard.js +1323 -0
  366. package/dist/game/wizard.js.map +1 -0
  367. package/dist/game/world.d.ts +183 -0
  368. package/dist/game/world.d.ts.map +1 -0
  369. package/dist/game/world.js +685 -0
  370. package/dist/game/world.js.map +1 -0
  371. package/dist/gen/cave.d.ts +247 -0
  372. package/dist/gen/cave.d.ts.map +1 -0
  373. package/dist/gen/cave.js +2406 -0
  374. package/dist/gen/cave.js.map +1 -0
  375. package/dist/gen/gen-monster.d.ts +151 -0
  376. package/dist/gen/gen-monster.d.ts.map +1 -0
  377. package/dist/gen/gen-monster.js +473 -0
  378. package/dist/gen/gen-monster.js.map +1 -0
  379. package/dist/gen/generate.d.ts +240 -0
  380. package/dist/gen/generate.d.ts.map +1 -0
  381. package/dist/gen/generate.js +358 -0
  382. package/dist/gen/generate.js.map +1 -0
  383. package/dist/gen/room.d.ts +160 -0
  384. package/dist/gen/room.d.ts.map +1 -0
  385. package/dist/gen/room.js +1910 -0
  386. package/dist/gen/room.js.map +1 -0
  387. package/dist/gen/util.d.ts +466 -0
  388. package/dist/gen/util.d.ts.map +1 -0
  389. package/dist/gen/util.js +1553 -0
  390. package/dist/gen/util.js.map +1 -0
  391. package/dist/generated/dun-profiles.d.ts +44 -0
  392. package/dist/generated/dun-profiles.d.ts.map +1 -0
  393. package/dist/generated/dun-profiles.js +28 -0
  394. package/dist/generated/dun-profiles.js.map +1 -0
  395. package/dist/generated/effects.d.ts +1021 -0
  396. package/dist/generated/effects.d.ts.map +1 -0
  397. package/dist/generated/effects.js +239 -0
  398. package/dist/generated/effects.js.map +1 -0
  399. package/dist/generated/elements.d.ts +83 -0
  400. package/dist/generated/elements.d.ts.map +1 -0
  401. package/dist/generated/elements.js +60 -0
  402. package/dist/generated/elements.js.map +1 -0
  403. package/dist/generated/equip-slots.d.ts +104 -0
  404. package/dist/generated/equip-slots.d.ts.map +1 -0
  405. package/dist/generated/equip-slots.js +34 -0
  406. package/dist/generated/equip-slots.js.map +1 -0
  407. package/dist/generated/history-types.d.ts +52 -0
  408. package/dist/generated/history-types.d.ts.map +1 -0
  409. package/dist/generated/history-types.js +32 -0
  410. package/dist/generated/history-types.js.map +1 -0
  411. package/dist/generated/ignore-types.d.ts +116 -0
  412. package/dist/generated/ignore-types.d.ts.map +1 -0
  413. package/dist/generated/ignore-types.js +64 -0
  414. package/dist/generated/ignore-types.js.map +1 -0
  415. package/dist/generated/index.d.ts +32 -0
  416. package/dist/generated/index.d.ts.map +1 -0
  417. package/dist/generated/index.js +33 -0
  418. package/dist/generated/index.js.map +1 -0
  419. package/dist/generated/kind-flags.d.ts +72 -0
  420. package/dist/generated/kind-flags.d.ts.map +1 -0
  421. package/dist/generated/kind-flags.js +42 -0
  422. package/dist/generated/kind-flags.js.map +1 -0
  423. package/dist/generated/message.d.ts +624 -0
  424. package/dist/generated/message.d.ts.map +1 -0
  425. package/dist/generated/message.js +318 -0
  426. package/dist/generated/message.js.map +1 -0
  427. package/dist/generated/mon-message.d.ts +386 -0
  428. package/dist/generated/mon-message.d.ts.map +1 -0
  429. package/dist/generated/mon-message.js +136 -0
  430. package/dist/generated/mon-message.js.map +1 -0
  431. package/dist/generated/mon-race-flags.d.ts +433 -0
  432. package/dist/generated/mon-race-flags.d.ts.map +1 -0
  433. package/dist/generated/mon-race-flags.js +180 -0
  434. package/dist/generated/mon-race-flags.js.map +1 -0
  435. package/dist/generated/mon-spells.d.ts +380 -0
  436. package/dist/generated/mon-spells.d.ts.map +1 -0
  437. package/dist/generated/mon-spells.js +196 -0
  438. package/dist/generated/mon-spells.js.map +1 -0
  439. package/dist/generated/mon-temp-flags.d.ts +52 -0
  440. package/dist/generated/mon-temp-flags.d.ts.map +1 -0
  441. package/dist/generated/mon-temp-flags.js +32 -0
  442. package/dist/generated/mon-temp-flags.js.map +1 -0
  443. package/dist/generated/mon-timed.d.ts +118 -0
  444. package/dist/generated/mon-timed.d.ts.map +1 -0
  445. package/dist/generated/mon-timed.js +32 -0
  446. package/dist/generated/mon-timed.js.map +1 -0
  447. package/dist/generated/object-flags.d.ts +169 -0
  448. package/dist/generated/object-flags.d.ts.map +1 -0
  449. package/dist/generated/object-flags.js +93 -0
  450. package/dist/generated/object-flags.js.map +1 -0
  451. package/dist/generated/object-modifiers.d.ts +50 -0
  452. package/dist/generated/object-modifiers.d.ts.map +1 -0
  453. package/dist/generated/object-modifiers.js +41 -0
  454. package/dist/generated/object-modifiers.js.map +1 -0
  455. package/dist/generated/options.d.ts +284 -0
  456. package/dist/generated/options.d.ts.map +1 -0
  457. package/dist/generated/options.js +102 -0
  458. package/dist/generated/options.js.map +1 -0
  459. package/dist/generated/origins.d.ts +138 -0
  460. package/dist/generated/origins.d.ts.map +1 -0
  461. package/dist/generated/origins.js +62 -0
  462. package/dist/generated/origins.js.map +1 -0
  463. package/dist/generated/parser-errors.d.ts +264 -0
  464. package/dist/generated/parser-errors.d.ts.map +1 -0
  465. package/dist/generated/parser-errors.js +138 -0
  466. package/dist/generated/parser-errors.js.map +1 -0
  467. package/dist/generated/player-flags.d.ts +62 -0
  468. package/dist/generated/player-flags.d.ts.map +1 -0
  469. package/dist/generated/player-flags.js +46 -0
  470. package/dist/generated/player-flags.js.map +1 -0
  471. package/dist/generated/player-timed.d.ts +273 -0
  472. package/dist/generated/player-timed.d.ts.map +1 -0
  473. package/dist/generated/player-timed.js +116 -0
  474. package/dist/generated/player-timed.js.map +1 -0
  475. package/dist/generated/projections.d.ts +130 -0
  476. package/dist/generated/projections.d.ts.map +1 -0
  477. package/dist/generated/projections.js +101 -0
  478. package/dist/generated/projections.js.map +1 -0
  479. package/dist/generated/randart-properties.d.ts +388 -0
  480. package/dist/generated/randart-properties.d.ts.map +1 -0
  481. package/dist/generated/randart-properties.js +200 -0
  482. package/dist/generated/randart-properties.js.map +1 -0
  483. package/dist/generated/room-flags.d.ts +21 -0
  484. package/dist/generated/room-flags.d.ts.map +1 -0
  485. package/dist/generated/room-flags.js +19 -0
  486. package/dist/generated/room-flags.js.map +1 -0
  487. package/dist/generated/rooms.d.ts +122 -0
  488. package/dist/generated/rooms.d.ts.map +1 -0
  489. package/dist/generated/rooms.js +48 -0
  490. package/dist/generated/rooms.js.map +1 -0
  491. package/dist/generated/square-flags.d.ts +96 -0
  492. package/dist/generated/square-flags.d.ts.map +1 -0
  493. package/dist/generated/square-flags.js +54 -0
  494. package/dist/generated/square-flags.js.map +1 -0
  495. package/dist/generated/stats.d.ts +23 -0
  496. package/dist/generated/stats.d.ts.map +1 -0
  497. package/dist/generated/stats.js +20 -0
  498. package/dist/generated/stats.js.map +1 -0
  499. package/dist/generated/terrain-flags.d.ts +136 -0
  500. package/dist/generated/terrain-flags.d.ts.map +1 -0
  501. package/dist/generated/terrain-flags.js +74 -0
  502. package/dist/generated/terrain-flags.js.map +1 -0
  503. package/dist/generated/terrain.d.ts +83 -0
  504. package/dist/generated/terrain.d.ts.map +1 -0
  505. package/dist/generated/terrain.js +60 -0
  506. package/dist/generated/terrain.js.map +1 -0
  507. package/dist/generated/trap-flags.d.ts +68 -0
  508. package/dist/generated/trap-flags.d.ts.map +1 -0
  509. package/dist/generated/trap-flags.js +40 -0
  510. package/dist/generated/trap-flags.js.map +1 -0
  511. package/dist/generated/tvals.d.ts +152 -0
  512. package/dist/generated/tvals.d.ts.map +1 -0
  513. package/dist/generated/tvals.js +82 -0
  514. package/dist/generated/tvals.js.map +1 -0
  515. package/dist/generated/ui-entry-renderers.d.ts +62 -0
  516. package/dist/generated/ui-entry-renderers.d.ts.map +1 -0
  517. package/dist/generated/ui-entry-renderers.js +22 -0
  518. package/dist/generated/ui-entry-renderers.js.map +1 -0
  519. package/dist/guard.d.ts +43 -0
  520. package/dist/guard.d.ts.map +1 -0
  521. package/dist/guard.js +65 -0
  522. package/dist/guard.js.map +1 -0
  523. package/dist/host/args.d.ts +129 -0
  524. package/dist/host/args.d.ts.map +1 -0
  525. package/dist/host/args.js +251 -0
  526. package/dist/host/args.js.map +1 -0
  527. package/dist/host/bridge.d.ts +61 -0
  528. package/dist/host/bridge.d.ts.map +1 -0
  529. package/dist/host/bridge.js +176 -0
  530. package/dist/host/bridge.js.map +1 -0
  531. package/dist/host/index.d.ts +18 -0
  532. package/dist/host/index.d.ts.map +1 -0
  533. package/dist/host/index.js +18 -0
  534. package/dist/host/index.js.map +1 -0
  535. package/dist/host/io.d.ts +169 -0
  536. package/dist/host/io.d.ts.map +1 -0
  537. package/dist/host/io.js +137 -0
  538. package/dist/host/io.js.map +1 -0
  539. package/dist/host/memory.d.ts +56 -0
  540. package/dist/host/memory.d.ts.map +1 -0
  541. package/dist/host/memory.js +105 -0
  542. package/dist/host/memory.js.map +1 -0
  543. package/dist/host/raw.d.ts +114 -0
  544. package/dist/host/raw.d.ts.map +1 -0
  545. package/dist/host/raw.js +107 -0
  546. package/dist/host/raw.js.map +1 -0
  547. package/dist/index.d.ts +180 -0
  548. package/dist/index.d.ts.map +1 -0
  549. package/dist/index.js +222 -0
  550. package/dist/index.js.map +1 -0
  551. package/dist/loc.d.ts +63 -0
  552. package/dist/loc.d.ts.map +1 -0
  553. package/dist/loc.js +128 -0
  554. package/dist/loc.js.map +1 -0
  555. package/dist/mod/hooks.d.ts +204 -0
  556. package/dist/mod/hooks.d.ts.map +1 -0
  557. package/dist/mod/hooks.js +161 -0
  558. package/dist/mod/hooks.js.map +1 -0
  559. package/dist/mod/ids.d.ts +160 -0
  560. package/dist/mod/ids.d.ts.map +1 -0
  561. package/dist/mod/ids.js +343 -0
  562. package/dist/mod/ids.js.map +1 -0
  563. package/dist/mod/registry-host.d.ts +156 -0
  564. package/dist/mod/registry-host.d.ts.map +1 -0
  565. package/dist/mod/registry-host.js +142 -0
  566. package/dist/mod/registry-host.js.map +1 -0
  567. package/dist/mod/save-blocks.d.ts +201 -0
  568. package/dist/mod/save-blocks.d.ts.map +1 -0
  569. package/dist/mod/save-blocks.js +640 -0
  570. package/dist/mod/save-blocks.js.map +1 -0
  571. package/dist/mod/vocabulary.d.ts +104 -0
  572. package/dist/mod/vocabulary.d.ts.map +1 -0
  573. package/dist/mod/vocabulary.js +0 -0
  574. package/dist/mod/vocabulary.js.map +1 -0
  575. package/dist/mon/bind.d.ts +266 -0
  576. package/dist/mon/bind.d.ts.map +1 -0
  577. package/dist/mon/bind.js +610 -0
  578. package/dist/mon/bind.js.map +1 -0
  579. package/dist/mon/desc.d.ts +72 -0
  580. package/dist/mon/desc.d.ts.map +1 -0
  581. package/dist/mon/desc.js +237 -0
  582. package/dist/mon/desc.js.map +1 -0
  583. package/dist/mon/knowledge-groups.d.ts +61 -0
  584. package/dist/mon/knowledge-groups.d.ts.map +1 -0
  585. package/dist/mon/knowledge-groups.js +121 -0
  586. package/dist/mon/knowledge-groups.js.map +1 -0
  587. package/dist/mon/lore-describe.d.ts +216 -0
  588. package/dist/mon/lore-describe.d.ts.map +1 -0
  589. package/dist/mon/lore-describe.js +1105 -0
  590. package/dist/mon/lore-describe.js.map +1 -0
  591. package/dist/mon/lore.d.ts +117 -0
  592. package/dist/mon/lore.d.ts.map +1 -0
  593. package/dist/mon/lore.js +221 -0
  594. package/dist/mon/lore.js.map +1 -0
  595. package/dist/mon/make.d.ts +147 -0
  596. package/dist/mon/make.d.ts.map +1 -0
  597. package/dist/mon/make.js +353 -0
  598. package/dist/mon/make.js.map +1 -0
  599. package/dist/mon/monster.d.ts +94 -0
  600. package/dist/mon/monster.d.ts.map +1 -0
  601. package/dist/mon/monster.js +90 -0
  602. package/dist/mon/monster.js.map +1 -0
  603. package/dist/mon/predicate.d.ts +87 -0
  604. package/dist/mon/predicate.d.ts.map +1 -0
  605. package/dist/mon/predicate.js +190 -0
  606. package/dist/mon/predicate.js.map +1 -0
  607. package/dist/mon/project-mon.d.ts +129 -0
  608. package/dist/mon/project-mon.d.ts.map +1 -0
  609. package/dist/mon/project-mon.js +652 -0
  610. package/dist/mon/project-mon.js.map +1 -0
  611. package/dist/mon/spell.d.ts +155 -0
  612. package/dist/mon/spell.d.ts.map +1 -0
  613. package/dist/mon/spell.js +355 -0
  614. package/dist/mon/spell.js.map +1 -0
  615. package/dist/mon/steal.d.ts +112 -0
  616. package/dist/mon/steal.d.ts.map +1 -0
  617. package/dist/mon/steal.js +163 -0
  618. package/dist/mon/steal.js.map +1 -0
  619. package/dist/mon/summon.d.ts +62 -0
  620. package/dist/mon/summon.d.ts.map +1 -0
  621. package/dist/mon/summon.js +111 -0
  622. package/dist/mon/summon.js.map +1 -0
  623. package/dist/mon/take-hit.d.ts +75 -0
  624. package/dist/mon/take-hit.d.ts.map +1 -0
  625. package/dist/mon/take-hit.js +122 -0
  626. package/dist/mon/take-hit.js.map +1 -0
  627. package/dist/mon/timed.d.ts +74 -0
  628. package/dist/mon/timed.d.ts.map +1 -0
  629. package/dist/mon/timed.js +219 -0
  630. package/dist/mon/timed.js.map +1 -0
  631. package/dist/mon/types.d.ts +252 -0
  632. package/dist/mon/types.d.ts.map +1 -0
  633. package/dist/mon/types.js +46 -0
  634. package/dist/mon/types.js.map +1 -0
  635. package/dist/msg.d.ts +71 -0
  636. package/dist/msg.d.ts.map +1 -0
  637. package/dist/msg.js +126 -0
  638. package/dist/msg.js.map +1 -0
  639. package/dist/obj/artifact-fake.d.ts +39 -0
  640. package/dist/obj/artifact-fake.d.ts.map +1 -0
  641. package/dist/obj/artifact-fake.js +52 -0
  642. package/dist/obj/artifact-fake.js.map +1 -0
  643. package/dist/obj/artifact-known.d.ts +50 -0
  644. package/dist/obj/artifact-known.d.ts.map +1 -0
  645. package/dist/obj/artifact-known.js +55 -0
  646. package/dist/obj/artifact-known.js.map +1 -0
  647. package/dist/obj/bind.d.ts +219 -0
  648. package/dist/obj/bind.d.ts.map +1 -0
  649. package/dist/obj/bind.js +1239 -0
  650. package/dist/obj/bind.js.map +1 -0
  651. package/dist/obj/chest.d.ts +91 -0
  652. package/dist/obj/chest.d.ts.map +1 -0
  653. package/dist/obj/chest.js +220 -0
  654. package/dist/obj/chest.js.map +1 -0
  655. package/dist/obj/desc.d.ts +79 -0
  656. package/dist/obj/desc.d.ts.map +1 -0
  657. package/dist/obj/desc.js +602 -0
  658. package/dist/obj/desc.js.map +1 -0
  659. package/dist/obj/effects-info.d.ts +78 -0
  660. package/dist/obj/effects-info.d.ts.map +1 -0
  661. package/dist/obj/effects-info.js +240 -0
  662. package/dist/obj/effects-info.js.map +1 -0
  663. package/dist/obj/flavor.d.ts +68 -0
  664. package/dist/obj/flavor.d.ts.map +1 -0
  665. package/dist/obj/flavor.js +201 -0
  666. package/dist/obj/flavor.js.map +1 -0
  667. package/dist/obj/ignore.d.ts +143 -0
  668. package/dist/obj/ignore.d.ts.map +1 -0
  669. package/dist/obj/ignore.js +345 -0
  670. package/dist/obj/ignore.js.map +1 -0
  671. package/dist/obj/knowledge.d.ts +520 -0
  672. package/dist/obj/knowledge.d.ts.map +1 -0
  673. package/dist/obj/knowledge.js +1364 -0
  674. package/dist/obj/knowledge.js.map +1 -0
  675. package/dist/obj/known-object.d.ts +293 -0
  676. package/dist/obj/known-object.d.ts.map +1 -0
  677. package/dist/obj/known-object.js +532 -0
  678. package/dist/obj/known-object.js.map +1 -0
  679. package/dist/obj/make.d.ts +292 -0
  680. package/dist/obj/make.d.ts.map +1 -0
  681. package/dist/obj/make.js +1055 -0
  682. package/dist/obj/make.js.map +1 -0
  683. package/dist/obj/object-info.d.ts +188 -0
  684. package/dist/obj/object-info.d.ts.map +1 -0
  685. package/dist/obj/object-info.js +1407 -0
  686. package/dist/obj/object-info.js.map +1 -0
  687. package/dist/obj/object.d.ts +335 -0
  688. package/dist/obj/object.d.ts.map +1 -0
  689. package/dist/obj/object.js +1051 -0
  690. package/dist/obj/object.js.map +1 -0
  691. package/dist/obj/power.d.ts +65 -0
  692. package/dist/obj/power.d.ts.map +1 -0
  693. package/dist/obj/power.js +580 -0
  694. package/dist/obj/power.js.map +1 -0
  695. package/dist/obj/randart-build.d.ts +223 -0
  696. package/dist/obj/randart-build.d.ts.map +1 -0
  697. package/dist/obj/randart-build.js +1444 -0
  698. package/dist/obj/randart-build.js.map +1 -0
  699. package/dist/obj/randart-data.d.ts +179 -0
  700. package/dist/obj/randart-data.d.ts.map +1 -0
  701. package/dist/obj/randart-data.js +1153 -0
  702. package/dist/obj/randart-data.js.map +1 -0
  703. package/dist/obj/randart.d.ts +128 -0
  704. package/dist/obj/randart.d.ts.map +1 -0
  705. package/dist/obj/randart.js +458 -0
  706. package/dist/obj/randart.js.map +1 -0
  707. package/dist/obj/randname.d.ts +33 -0
  708. package/dist/obj/randname.d.ts.map +1 -0
  709. package/dist/obj/randname.js +116 -0
  710. package/dist/obj/randname.js.map +1 -0
  711. package/dist/obj/recharge.d.ts +28 -0
  712. package/dist/obj/recharge.d.ts.map +1 -0
  713. package/dist/obj/recharge.js +52 -0
  714. package/dist/obj/recharge.js.map +1 -0
  715. package/dist/obj/types.d.ts +584 -0
  716. package/dist/obj/types.d.ts.map +1 -0
  717. package/dist/obj/types.js +104 -0
  718. package/dist/obj/types.js.map +1 -0
  719. package/dist/obj/value.d.ts +64 -0
  720. package/dist/obj/value.d.ts.map +1 -0
  721. package/dist/obj/value.js +176 -0
  722. package/dist/obj/value.js.map +1 -0
  723. package/dist/player/abilities.d.ts +57 -0
  724. package/dist/player/abilities.d.ts.map +1 -0
  725. package/dist/player/abilities.js +118 -0
  726. package/dist/player/abilities.js.map +1 -0
  727. package/dist/player/best-digger.d.ts +42 -0
  728. package/dist/player/best-digger.d.ts.map +1 -0
  729. package/dist/player/best-digger.js +89 -0
  730. package/dist/player/best-digger.js.map +1 -0
  731. package/dist/player/bind.d.ts +270 -0
  732. package/dist/player/bind.d.ts.map +1 -0
  733. package/dist/player/bind.js +698 -0
  734. package/dist/player/bind.js.map +1 -0
  735. package/dist/player/birth.d.ts +258 -0
  736. package/dist/player/birth.d.ts.map +1 -0
  737. package/dist/player/birth.js +639 -0
  738. package/dist/player/birth.js.map +1 -0
  739. package/dist/player/calcs.d.ts +403 -0
  740. package/dist/player/calcs.d.ts.map +1 -0
  741. package/dist/player/calcs.js +1189 -0
  742. package/dist/player/calcs.js.map +1 -0
  743. package/dist/player/combat-regen.d.ts +14 -0
  744. package/dist/player/combat-regen.d.ts.map +1 -0
  745. package/dist/player/combat-regen.js +29 -0
  746. package/dist/player/combat-regen.js.map +1 -0
  747. package/dist/player/exp.d.ts +96 -0
  748. package/dist/player/exp.d.ts.map +1 -0
  749. package/dist/player/exp.js +229 -0
  750. package/dist/player/exp.js.map +1 -0
  751. package/dist/player/history.d.ts +91 -0
  752. package/dist/player/history.d.ts.map +1 -0
  753. package/dist/player/history.js +145 -0
  754. package/dist/player/history.js.map +1 -0
  755. package/dist/player/options.d.ts +123 -0
  756. package/dist/player/options.d.ts.map +1 -0
  757. package/dist/player/options.js +199 -0
  758. package/dist/player/options.js.map +1 -0
  759. package/dist/player/player.d.ts +242 -0
  760. package/dist/player/player.d.ts.map +1 -0
  761. package/dist/player/player.js +119 -0
  762. package/dist/player/player.js.map +1 -0
  763. package/dist/player/shape-lore.d.ts +56 -0
  764. package/dist/player/shape-lore.d.ts.map +1 -0
  765. package/dist/player/shape-lore.js +221 -0
  766. package/dist/player/shape-lore.js.map +1 -0
  767. package/dist/player/spell.d.ts +146 -0
  768. package/dist/player/spell.d.ts.map +1 -0
  769. package/dist/player/spell.js +519 -0
  770. package/dist/player/spell.js.map +1 -0
  771. package/dist/player/take-hit.d.ts +87 -0
  772. package/dist/player/take-hit.d.ts.map +1 -0
  773. package/dist/player/take-hit.js +99 -0
  774. package/dist/player/take-hit.js.map +1 -0
  775. package/dist/player/timed.d.ts +205 -0
  776. package/dist/player/timed.d.ts.map +1 -0
  777. package/dist/player/timed.js +310 -0
  778. package/dist/player/timed.js.map +1 -0
  779. package/dist/player/types.d.ts +390 -0
  780. package/dist/player/types.d.ts.map +1 -0
  781. package/dist/player/types.js +51 -0
  782. package/dist/player/types.js.map +1 -0
  783. package/dist/rational.d.ts +99 -0
  784. package/dist/rational.d.ts.map +1 -0
  785. package/dist/rational.js +345 -0
  786. package/dist/rational.js.map +1 -0
  787. package/dist/rng.d.ts +168 -0
  788. package/dist/rng.d.ts.map +1 -0
  789. package/dist/rng.js +404 -0
  790. package/dist/rng.js.map +1 -0
  791. package/dist/save/buffer.d.ts +120 -0
  792. package/dist/save/buffer.d.ts.map +1 -0
  793. package/dist/save/buffer.js +238 -0
  794. package/dist/save/buffer.js.map +1 -0
  795. package/dist/save/compress.d.ts +79 -0
  796. package/dist/save/compress.d.ts.map +1 -0
  797. package/dist/save/compress.js +97 -0
  798. package/dist/save/compress.js.map +1 -0
  799. package/dist/save/description.d.ts +61 -0
  800. package/dist/save/description.d.ts.map +1 -0
  801. package/dist/save/description.js +51 -0
  802. package/dist/save/description.js.map +1 -0
  803. package/dist/save/integrity.d.ts +59 -0
  804. package/dist/save/integrity.d.ts.map +1 -0
  805. package/dist/save/integrity.js +103 -0
  806. package/dist/save/integrity.js.map +1 -0
  807. package/dist/score/display.d.ts +40 -0
  808. package/dist/score/display.d.ts.map +1 -0
  809. package/dist/score/display.js +86 -0
  810. package/dist/score/display.js.map +1 -0
  811. package/dist/score/score.d.ts +166 -0
  812. package/dist/score/score.d.ts.map +1 -0
  813. package/dist/score/score.js +244 -0
  814. package/dist/score/score.js.map +1 -0
  815. package/dist/score/types.d.ts +98 -0
  816. package/dist/score/types.d.ts.map +1 -0
  817. package/dist/score/types.js +27 -0
  818. package/dist/score/types.js.map +1 -0
  819. package/dist/session/boot.d.ts +207 -0
  820. package/dist/session/boot.d.ts.map +1 -0
  821. package/dist/session/boot.js +151 -0
  822. package/dist/session/boot.js.map +1 -0
  823. package/dist/session/game.d.ts +257 -0
  824. package/dist/session/game.d.ts.map +1 -0
  825. package/dist/session/game.js +2880 -0
  826. package/dist/session/game.js.map +1 -0
  827. package/dist/session/save.d.ts +847 -0
  828. package/dist/session/save.d.ts.map +1 -0
  829. package/dist/session/save.js +1306 -0
  830. package/dist/session/save.js.map +1 -0
  831. package/dist/sound/engine.d.ts +146 -0
  832. package/dist/sound/engine.d.ts.map +1 -0
  833. package/dist/sound/engine.js +332 -0
  834. package/dist/sound/engine.js.map +1 -0
  835. package/dist/sound/index.d.ts +13 -0
  836. package/dist/sound/index.d.ts.map +1 -0
  837. package/dist/sound/index.js +13 -0
  838. package/dist/sound/index.js.map +1 -0
  839. package/dist/sound/sound-prefs-data.d.ts +10 -0
  840. package/dist/sound/sound-prefs-data.d.ts.map +1 -0
  841. package/dist/sound/sound-prefs-data.js +165 -0
  842. package/dist/sound/sound-prefs-data.js.map +1 -0
  843. package/dist/sound/types.d.ts +64 -0
  844. package/dist/sound/types.d.ts.map +1 -0
  845. package/dist/sound/types.js +23 -0
  846. package/dist/sound/types.js.map +1 -0
  847. package/dist/store/bind.d.ts +43 -0
  848. package/dist/store/bind.d.ts.map +1 -0
  849. package/dist/store/bind.js +130 -0
  850. package/dist/store/bind.js.map +1 -0
  851. package/dist/store/price.d.ts +27 -0
  852. package/dist/store/price.d.ts.map +1 -0
  853. package/dist/store/price.js +81 -0
  854. package/dist/store/price.js.map +1 -0
  855. package/dist/store/store-cmd.d.ts +51 -0
  856. package/dist/store/store-cmd.d.ts.map +1 -0
  857. package/dist/store/store-cmd.js +73 -0
  858. package/dist/store/store-cmd.js.map +1 -0
  859. package/dist/store/store.d.ts +156 -0
  860. package/dist/store/store.d.ts.map +1 -0
  861. package/dist/store/store.js +616 -0
  862. package/dist/store/store.js.map +1 -0
  863. package/dist/store/transact.d.ts +198 -0
  864. package/dist/store/transact.d.ts.map +1 -0
  865. package/dist/store/transact.js +383 -0
  866. package/dist/store/transact.js.map +1 -0
  867. package/dist/store/types.d.ts +101 -0
  868. package/dist/store/types.d.ts.map +1 -0
  869. package/dist/store/types.js +14 -0
  870. package/dist/store/types.js.map +1 -0
  871. package/dist/version.d.ts +25 -0
  872. package/dist/version.d.ts.map +1 -0
  873. package/dist/version.js +25 -0
  874. package/dist/version.js.map +1 -0
  875. package/dist/visuals/engine.d.ts +223 -0
  876. package/dist/visuals/engine.d.ts.map +1 -0
  877. package/dist/visuals/engine.js +357 -0
  878. package/dist/visuals/engine.js.map +1 -0
  879. package/dist/visuals/glyph-table.d.ts +112 -0
  880. package/dist/visuals/glyph-table.d.ts.map +1 -0
  881. package/dist/visuals/glyph-table.js +156 -0
  882. package/dist/visuals/glyph-table.js.map +1 -0
  883. package/dist/visuals/grafmode-data.d.ts +4 -0
  884. package/dist/visuals/grafmode-data.d.ts.map +1 -0
  885. package/dist/visuals/grafmode-data.js +88 -0
  886. package/dist/visuals/grafmode-data.js.map +1 -0
  887. package/dist/visuals/grafmode.d.ts +83 -0
  888. package/dist/visuals/grafmode.d.ts.map +1 -0
  889. package/dist/visuals/grafmode.js +82 -0
  890. package/dist/visuals/grafmode.js.map +1 -0
  891. package/dist/visuals/index.d.ts +19 -0
  892. package/dist/visuals/index.d.ts.map +1 -0
  893. package/dist/visuals/index.js +19 -0
  894. package/dist/visuals/index.js.map +1 -0
  895. package/dist/visuals/map-text.d.ts +79 -0
  896. package/dist/visuals/map-text.d.ts.map +1 -0
  897. package/dist/visuals/map-text.js +122 -0
  898. package/dist/visuals/map-text.js.map +1 -0
  899. package/dist/visuals/pref-expr.d.ts +56 -0
  900. package/dist/visuals/pref-expr.d.ts.map +1 -0
  901. package/dist/visuals/pref-expr.js +173 -0
  902. package/dist/visuals/pref-expr.js.map +1 -0
  903. package/dist/visuals/prefs.d.ts +280 -0
  904. package/dist/visuals/prefs.d.ts.map +1 -0
  905. package/dist/visuals/prefs.js +835 -0
  906. package/dist/visuals/prefs.js.map +1 -0
  907. package/dist/visuals/tile-prefs.d.ts +132 -0
  908. package/dist/visuals/tile-prefs.d.ts.map +1 -0
  909. package/dist/visuals/tile-prefs.js +105 -0
  910. package/dist/visuals/tile-prefs.js.map +1 -0
  911. package/dist/world/chunk.d.ts +195 -0
  912. package/dist/world/chunk.d.ts.map +1 -0
  913. package/dist/world/chunk.js +422 -0
  914. package/dist/world/chunk.js.map +1 -0
  915. package/dist/world/feature.d.ts +86 -0
  916. package/dist/world/feature.d.ts.map +1 -0
  917. package/dist/world/feature.js +153 -0
  918. package/dist/world/feature.js.map +1 -0
  919. package/dist/world/flow.d.ts +33 -0
  920. package/dist/world/flow.d.ts.map +1 -0
  921. package/dist/world/flow.js +115 -0
  922. package/dist/world/flow.js.map +1 -0
  923. package/dist/world/project.d.ts +176 -0
  924. package/dist/world/project.d.ts.map +1 -0
  925. package/dist/world/project.js +543 -0
  926. package/dist/world/project.js.map +1 -0
  927. package/dist/world/projection.d.ts +100 -0
  928. package/dist/world/projection.d.ts.map +1 -0
  929. package/dist/world/projection.js +152 -0
  930. package/dist/world/projection.js.map +1 -0
  931. package/dist/world/scatter.d.ts +25 -0
  932. package/dist/world/scatter.d.ts.map +1 -0
  933. package/dist/world/scatter.js +54 -0
  934. package/dist/world/scatter.js.map +1 -0
  935. package/dist/world/trap.d.ts +84 -0
  936. package/dist/world/trap.d.ts.map +1 -0
  937. package/dist/world/trap.js +106 -0
  938. package/dist/world/trap.js.map +1 -0
  939. package/dist/world/view.d.ts +60 -0
  940. package/dist/world/view.d.ts.map +1 -0
  941. package/dist/world/view.js +436 -0
  942. package/dist/world/view.js.map +1 -0
  943. package/dist/z-queue.d.ts +133 -0
  944. package/dist/z-queue.d.ts.map +1 -0
  945. package/dist/z-queue.js +283 -0
  946. package/dist/z-queue.js.map +1 -0
  947. package/package.json +75 -0
  948. package/src/agent/act.ts +114 -0
  949. package/src/agent/controller.ts +109 -0
  950. package/src/agent/events.ts +47 -0
  951. package/src/agent/index.ts +36 -0
  952. package/src/agent/perceive.ts +440 -0
  953. package/src/agent/types.ts +464 -0
  954. package/src/bitflag.ts +536 -0
  955. package/src/cmd.ts +547 -0
  956. package/src/color.ts +267 -0
  957. package/src/combat/brand-slay.ts +360 -0
  958. package/src/combat/hit.ts +471 -0
  959. package/src/combat/index.ts +15 -0
  960. package/src/combat/melee.ts +728 -0
  961. package/src/combat/mon-melee.ts +1153 -0
  962. package/src/combat/ranged.ts +397 -0
  963. package/src/constants.ts +324 -0
  964. package/src/dice.ts +467 -0
  965. package/src/effects/effect-choice.ts +32 -0
  966. package/src/effects/effect-info.ts +859 -0
  967. package/src/effects/effect.ts +560 -0
  968. package/src/effects/handlers.ts +452 -0
  969. package/src/effects/interpreter.ts +603 -0
  970. package/src/events.ts +317 -0
  971. package/src/expression.ts +360 -0
  972. package/src/game/cave-cmd.ts +1147 -0
  973. package/src/game/char-sheet.ts +557 -0
  974. package/src/game/chest.ts +348 -0
  975. package/src/game/context.ts +1218 -0
  976. package/src/game/curse-tick.ts +130 -0
  977. package/src/game/describe.ts +62 -0
  978. package/src/game/display.ts +838 -0
  979. package/src/game/dump-level.ts +114 -0
  980. package/src/game/effect-attack.ts +746 -0
  981. package/src/game/effect-detect.ts +542 -0
  982. package/src/game/effect-env.ts +252 -0
  983. package/src/game/effect-game-env.ts +86 -0
  984. package/src/game/effect-general.ts +1122 -0
  985. package/src/game/effect-item.ts +999 -0
  986. package/src/game/effect-melee.ts +557 -0
  987. package/src/game/effect-mon-origin.ts +196 -0
  988. package/src/game/effect-monster.ts +310 -0
  989. package/src/game/effect-summon.ts +161 -0
  990. package/src/game/effect-teleport.ts +645 -0
  991. package/src/game/effect-terrain.ts +881 -0
  992. package/src/game/energy.ts +61 -0
  993. package/src/game/equip-cmp.ts +476 -0
  994. package/src/game/floor.ts +524 -0
  995. package/src/game/gear.ts +1352 -0
  996. package/src/game/harness.ts +270 -0
  997. package/src/game/history.ts +78 -0
  998. package/src/game/ignore-cmd.ts +68 -0
  999. package/src/game/inscription-confirm.ts +115 -0
  1000. package/src/game/known.ts +960 -0
  1001. package/src/game/loop.ts +671 -0
  1002. package/src/game/lore-color.ts +108 -0
  1003. package/src/game/mon-cast.ts +409 -0
  1004. package/src/game/mon-cmd.ts +767 -0
  1005. package/src/game/mon-death.ts +459 -0
  1006. package/src/game/mon-group.ts +368 -0
  1007. package/src/game/mon-list.ts +213 -0
  1008. package/src/game/mon-message.ts +359 -0
  1009. package/src/game/mon-place.ts +1012 -0
  1010. package/src/game/mon-ranged.ts +405 -0
  1011. package/src/game/mon-shape.ts +161 -0
  1012. package/src/game/mon-side.ts +511 -0
  1013. package/src/game/monster-turn.ts +1750 -0
  1014. package/src/game/obj-cmd.ts +1970 -0
  1015. package/src/game/obj-list.ts +302 -0
  1016. package/src/game/object-inspect.ts +162 -0
  1017. package/src/game/pickup.ts +483 -0
  1018. package/src/game/player-path.ts +1434 -0
  1019. package/src/game/player-side.ts +555 -0
  1020. package/src/game/player-turn.ts +852 -0
  1021. package/src/game/project-cast.ts +766 -0
  1022. package/src/game/project-feat.ts +386 -0
  1023. package/src/game/project-monster.ts +407 -0
  1024. package/src/game/project-obj.ts +298 -0
  1025. package/src/game/project-player.ts +236 -0
  1026. package/src/game/quest.ts +248 -0
  1027. package/src/game/ranged-cmd.ts +417 -0
  1028. package/src/game/scheduler.ts +150 -0
  1029. package/src/game/spell-cmd.ts +404 -0
  1030. package/src/game/spoil.ts +562 -0
  1031. package/src/game/steal.ts +169 -0
  1032. package/src/game/take-hit-hooks.ts +152 -0
  1033. package/src/game/target-loop.ts +501 -0
  1034. package/src/game/target.ts +424 -0
  1035. package/src/game/thrust.ts +174 -0
  1036. package/src/game/trap.ts +791 -0
  1037. package/src/game/ui-entry.ts +2075 -0
  1038. package/src/game/wizard.ts +1760 -0
  1039. package/src/game/world.ts +786 -0
  1040. package/src/gen/cave.ts +2858 -0
  1041. package/src/gen/gen-monster.ts +592 -0
  1042. package/src/gen/generate.ts +523 -0
  1043. package/src/gen/room.ts +2213 -0
  1044. package/src/gen/util.ts +1958 -0
  1045. package/src/generated/dun-profiles.ts +30 -0
  1046. package/src/generated/effects.ts +241 -0
  1047. package/src/generated/elements.ts +62 -0
  1048. package/src/generated/equip-slots.ts +36 -0
  1049. package/src/generated/history-types.ts +34 -0
  1050. package/src/generated/ignore-types.ts +66 -0
  1051. package/src/generated/index.ts +33 -0
  1052. package/src/generated/kind-flags.ts +44 -0
  1053. package/src/generated/message.ts +320 -0
  1054. package/src/generated/mon-message.ts +138 -0
  1055. package/src/generated/mon-race-flags.ts +182 -0
  1056. package/src/generated/mon-spells.ts +198 -0
  1057. package/src/generated/mon-temp-flags.ts +34 -0
  1058. package/src/generated/mon-timed.ts +34 -0
  1059. package/src/generated/object-flags.ts +95 -0
  1060. package/src/generated/object-modifiers.ts +43 -0
  1061. package/src/generated/options.ts +104 -0
  1062. package/src/generated/origins.ts +64 -0
  1063. package/src/generated/parser-errors.ts +140 -0
  1064. package/src/generated/player-flags.ts +48 -0
  1065. package/src/generated/player-timed.ts +118 -0
  1066. package/src/generated/projections.ts +103 -0
  1067. package/src/generated/randart-properties.ts +202 -0
  1068. package/src/generated/room-flags.ts +21 -0
  1069. package/src/generated/rooms.ts +50 -0
  1070. package/src/generated/square-flags.ts +56 -0
  1071. package/src/generated/stats.ts +22 -0
  1072. package/src/generated/terrain-flags.ts +76 -0
  1073. package/src/generated/terrain.ts +62 -0
  1074. package/src/generated/trap-flags.ts +42 -0
  1075. package/src/generated/tvals.ts +84 -0
  1076. package/src/generated/ui-entry-renderers.ts +24 -0
  1077. package/src/guard.ts +70 -0
  1078. package/src/host/args.ts +334 -0
  1079. package/src/host/bridge.ts +193 -0
  1080. package/src/host/index.ts +18 -0
  1081. package/src/host/io.ts +239 -0
  1082. package/src/host/memory.ts +134 -0
  1083. package/src/host/raw.ts +190 -0
  1084. package/src/index.ts +250 -0
  1085. package/src/loc.ts +157 -0
  1086. package/src/mod/hooks.ts +278 -0
  1087. package/src/mod/ids.ts +390 -0
  1088. package/src/mod/registry-host.ts +258 -0
  1089. package/src/mod/save-blocks.ts +787 -0
  1090. package/src/mod/vocabulary.ts +0 -0
  1091. package/src/mon/bind.ts +899 -0
  1092. package/src/mon/desc.ts +212 -0
  1093. package/src/mon/knowledge-groups.ts +164 -0
  1094. package/src/mon/lore-describe.ts +1414 -0
  1095. package/src/mon/lore.ts +306 -0
  1096. package/src/mon/make.ts +422 -0
  1097. package/src/mon/monster.ts +161 -0
  1098. package/src/mon/predicate.ts +220 -0
  1099. package/src/mon/project-mon.ts +855 -0
  1100. package/src/mon/spell.ts +418 -0
  1101. package/src/mon/steal.ts +246 -0
  1102. package/src/mon/summon.ts +145 -0
  1103. package/src/mon/take-hit.ts +195 -0
  1104. package/src/mon/timed.ts +300 -0
  1105. package/src/mon/types.ts +286 -0
  1106. package/src/msg.ts +146 -0
  1107. package/src/obj/artifact-fake.ts +63 -0
  1108. package/src/obj/artifact-known.ts +69 -0
  1109. package/src/obj/bind.ts +1345 -0
  1110. package/src/obj/chest.ts +249 -0
  1111. package/src/obj/desc.ts +699 -0
  1112. package/src/obj/effects-info.ts +349 -0
  1113. package/src/obj/flavor.ts +256 -0
  1114. package/src/obj/ignore.ts +387 -0
  1115. package/src/obj/knowledge.ts +1577 -0
  1116. package/src/obj/known-object.ts +718 -0
  1117. package/src/obj/make.ts +1367 -0
  1118. package/src/obj/object-info.ts +1737 -0
  1119. package/src/obj/object.ts +1296 -0
  1120. package/src/obj/power.ts +674 -0
  1121. package/src/obj/randart-build.ts +1705 -0
  1122. package/src/obj/randart-data.ts +1344 -0
  1123. package/src/obj/randart.ts +552 -0
  1124. package/src/obj/randname.ts +128 -0
  1125. package/src/obj/recharge.ts +62 -0
  1126. package/src/obj/types.ts +559 -0
  1127. package/src/obj/value.ts +215 -0
  1128. package/src/player/abilities.ts +142 -0
  1129. package/src/player/best-digger.ts +118 -0
  1130. package/src/player/bind.ts +1021 -0
  1131. package/src/player/birth.ts +794 -0
  1132. package/src/player/calcs.ts +1522 -0
  1133. package/src/player/combat-regen.ts +33 -0
  1134. package/src/player/exp.ts +275 -0
  1135. package/src/player/history.ts +211 -0
  1136. package/src/player/options.ts +244 -0
  1137. package/src/player/player.ts +356 -0
  1138. package/src/player/shape-lore.ts +250 -0
  1139. package/src/player/spell.ts +627 -0
  1140. package/src/player/take-hit.ts +173 -0
  1141. package/src/player/timed.ts +482 -0
  1142. package/src/player/types.ts +415 -0
  1143. package/src/rational.ts +388 -0
  1144. package/src/rng.ts +476 -0
  1145. package/src/save/buffer.ts +287 -0
  1146. package/src/save/compress.ts +132 -0
  1147. package/src/save/description.ts +70 -0
  1148. package/src/save/integrity.ts +133 -0
  1149. package/src/score/display.ts +125 -0
  1150. package/src/score/score.ts +341 -0
  1151. package/src/score/types.ts +104 -0
  1152. package/src/session/boot.ts +338 -0
  1153. package/src/session/game.ts +3712 -0
  1154. package/src/session/save.ts +2074 -0
  1155. package/src/sound/engine.ts +375 -0
  1156. package/src/sound/index.ts +13 -0
  1157. package/src/sound/sound-prefs-data.ts +173 -0
  1158. package/src/sound/types.ts +68 -0
  1159. package/src/store/bind.ts +145 -0
  1160. package/src/store/price.ts +97 -0
  1161. package/src/store/store-cmd.ts +73 -0
  1162. package/src/store/store.ts +723 -0
  1163. package/src/store/transact.ts +644 -0
  1164. package/src/store/types.ts +110 -0
  1165. package/src/version.ts +26 -0
  1166. package/src/visuals/engine.ts +444 -0
  1167. package/src/visuals/glyph-table.ts +191 -0
  1168. package/src/visuals/grafmode-data.ts +90 -0
  1169. package/src/visuals/grafmode.ts +123 -0
  1170. package/src/visuals/index.ts +19 -0
  1171. package/src/visuals/map-text.ts +152 -0
  1172. package/src/visuals/pref-expr.ts +182 -0
  1173. package/src/visuals/prefs.ts +981 -0
  1174. package/src/visuals/tile-prefs.ts +183 -0
  1175. package/src/world/chunk.ts +531 -0
  1176. package/src/world/feature.ts +215 -0
  1177. package/src/world/flow.ts +128 -0
  1178. package/src/world/project.ts +687 -0
  1179. package/src/world/projection.ts +228 -0
  1180. package/src/world/scatter.ts +72 -0
  1181. package/src/world/trap.ts +155 -0
  1182. package/src/world/view.ts +513 -0
  1183. package/src/z-queue.ts +300 -0
@@ -0,0 +1,1560 @@
1
+ /**
2
+ * process_monster and the mon-move.c monster AI, ported from
3
+ * reference/src/mon-move.c (Angband 4.2.6) as faithfully as the ported
4
+ * subset of the world allows.
5
+ *
6
+ * PORTED:
7
+ * - get_move_find_range: min_range / best_range (fear flight distance, the
8
+ * level/health comparison that scares weak monsters, the never-move /
9
+ * never-blow stand-off bonus, turn_range "nearby monsters won't run").
10
+ * - get_move_advance: pass-wall beeline, line-of-sight beeline, then sound
11
+ * (the cave->noise flow heatmap from world/flow) with the cardinal-first
12
+ * 8-direction scan, then scent. This is the flow-following core.
13
+ * - get_move: advance vs. the tracking fallback / random step, the afraid
14
+ * flee branch, get_move_choose_direction (the vertical/horizontal/diagonal
15
+ * preference with the turn-parity tie-break), MFLAG_TRACKING.
16
+ * - monster_turn_should_stagger: RAND_25 / RAND_50 erratic movement and the
17
+ * confusion staggers (CONF_ERRATIC_CHANCE per confusion grade).
18
+ * - monster_turn: the 5-step side_dirs movement loop, the tracking early-out,
19
+ * NEVER_MOVE, attack the player via combat.monMeleeAttack, push past / kill
20
+ * a blocking monster, and the "paralysed by fear" fallback.
21
+ * - process_monster_timed (sleep/wake, timer decrement, hold/stun miss) and
22
+ * monster_check_active.
23
+ *
24
+ * NOW WIRED (was deferred): make_ranged_attack via the state.monsterCast
25
+ * hook, monster_group_rouse before it, and group_monster_tracking in
26
+ * get_move's fallback branch.
27
+ *
28
+ * NOW PORTED (this pass, one coherent RNG-order-preserving change):
29
+ * - Fleeing geometry: get_move_find_safety (the dist_offsets ring scan for a
30
+ * reachable out-of-view grid) and the swerving get_move_flee, wired into the
31
+ * afraid branch of get_move exactly as upstream (find_safety -> flee for a
32
+ * course, else leg it away). Both draw no RNG.
33
+ * - Terrain manipulation in monster_turn_can_move: OPEN_DOOR / BASH_DOOR
34
+ * (with the confused one_in_(3) bash chance, the one_in_(2) open-vs-bash
35
+ * choice, and the locked-door randint0(hp/10) strength test seamed to the
36
+ * trap system) and KILL_WALL / SMASH_WALL (square_smash_wall's per-adjacent
37
+ * granite/quartz/magma survival rolls) / PASS_WALL, plus the confused-move
38
+ * self-stun. The "can move here" predicate stays distinct from "did the
39
+ * terrain action" (the did-something flag that spends the turn).
40
+ * - Reproduction: monster_turn_multiply (the num_repro cap, arena block, the
41
+ * 3x3 neighbour count and the one_in_(k * repro_monster_rate) chance) calling
42
+ * multiply_monster through the state.monsterMultiply hook. Runs before the
43
+ * ranged attack, matching upstream's process_monster order.
44
+ * - Item pickup/crush: monster_turn_grab_objects (TAKE_ITEM copies the floor
45
+ * object into the monster's held pile, KILL_ITEM crushes it; gold, mimics and
46
+ * artifacts are left; draws no RNG).
47
+ * - Aggravation: monster_reduce_sleep consults player OF_AGGRAVATE first and
48
+ * wakes the monster (drawing monster_wake's randint0(100) instead of the
49
+ * notice roll), matching the upstream if/else.
50
+ * - Camouflage/mimic reveal: monster_turn_try_push reveals a camouflaged
51
+ * blocker before it is trampled (mon-move.c L1352), and monster_turn itself
52
+ * reveals a camouflaged mon that did_something on its turn (L1680), both via
53
+ * the injected state.becomeAware hook (game/known.ts becomeAware, installed
54
+ * by session/game.ts). monster_turn_multiply's "reveal a camouflaged child
55
+ * of an already-revealed breeder" (L1002-1011) is ported alongside it in
56
+ * game/mon-place.ts multiplyMonster. Draws no RNG.
57
+ *
58
+ * NOW PORTED (this pass):
59
+ * - Group AI: get_move_bodyguard (a bodyguard stays adjacent to its group
60
+ * leader, wired into the top of get_move_advance) and the RF_GROUP_AI pack
61
+ * ambush branch of get_move (the open-grid count around the player, then
62
+ * get_move_find_hiding - the flow/projectable ring scan that finds a hidden
63
+ * grid to lie in wait). Both draw no RNG.
64
+ * - Damaging terrain (square_isdamaging is feat_is_fiery / lava in 4.2.6, and
65
+ * lava with resist-flag IM_FIRE IS modelled): monster_hates_grid (avoid it in
66
+ * advance/random/find_safety/bodyguard/can_move) and monster_taking_terrain_
67
+ * damage (the get_move terrain-flight branch, the get_move_flee early-out, and
68
+ * the monster_check_active activation). All draw no RNG.
69
+ * - Glyph: monster_turn_attack_glyph (a monster on a warded grid rolls
70
+ * randint1(glyph_hardness) < level to break the ward). Decoy: monster is
71
+ * decoyed -> target the decoy (get_move_advance / get_move), attack-allowed in
72
+ * can_move, and square_destroy_decoy when stepped on (draws no RNG; the decoy
73
+ * is disambiguated from a glyph of warding by cave->decoy since both traps
74
+ * share the GLYPH flag). Web: a webbed monster passes / clears / is stuck by
75
+ * RF_PASS_WEB / RF_CLEAR_WEB / pass-walls (draws no RNG).
76
+ *
77
+ * DEFERRED (ledgered in parity/ledger/game-monster-ai.yaml):
78
+ * - monster_take_terrain_damage (the actual lava damage after the turn, called
79
+ * from process_monster, not monster_turn): needs mon_take_nonplayer_hit
80
+ * (monster_death / delete_monster_idx), which is not ported; only the
81
+ * movement-driving predicate is ported here.
82
+ * - react_to_slay pickup safety, the confused-move / door-burst / glyph-break /
83
+ * decoy-destroy UI messages and disturb, and the remaining monster-lore
84
+ * updates. None of these draw RNG until taken, so the RNG order for the ported
85
+ * paths is unaffected.
86
+ */
87
+ import { DDD, DDGRID, DDGRID_DDD, SIDE_DIRS, distance, loc, locDiff, locEq, locIsZero, locSum, } from "../loc.js";
88
+ import { FEAT, MFLAG, MON_TMD, MSG, OF, RF, SQUARE, TF, TMD, TRF } from "../generated/index.js";
89
+ import { MON_GROUP } from "../mon/types.js";
90
+ import { monsterBreathes, monsterIsCamouflaged, monsterIsInView, monsterIsObvious, monsterIsUnique, monsterIsVisible, monsterLovesArchery, monsterPassesWalls, } from "../mon/predicate.js";
91
+ import { MDESC, monsterDesc } from "../mon/desc.js";
92
+ import { getLore, loreCountU16, loreCountU8, loreLearnFlagIfVisible, loreUpdate, } from "../mon/lore.js";
93
+ import { monsterRevertShape } from "./mon-shape.js";
94
+ import { monsterCarry } from "../mon/make.js";
95
+ import { monsterWake } from "../mon/take-hit.js";
96
+ import { MON_TMD_FLG_NOMESSAGE, MON_TMD_FLG_NOTIFY, monClearTimed, monDecTimed, monIncTimed, monsterEffectLevel, } from "../mon/timed.js";
97
+ import { formatMonsterMessageByName } from "./mon-message.js";
98
+ import { tvalIsMoney } from "../obj/object.js";
99
+ import { monMeleeAttack } from "../combat/mon-melee.js";
100
+ import { reactToSlay } from "../combat/brand-slay.js";
101
+ import { equipLearnOnDefend } from "../obj/knowledge.js";
102
+ import { updatePlayerObjectKnowledge } from "./known.js";
103
+ import { los, squareIsSeen, squareIsView } from "../world/view.js";
104
+ import { PROJECT, projectPath, projectable } from "../world/project.js";
105
+ import { deleteMonster, monsterSwap, squareIsPlayer, squareMonster, } from "./context.js";
106
+ import { disturb } from "./player-path.js";
107
+ import { floorExcise, floorPile } from "./floor.js";
108
+ import { describeObject } from "./describe.js";
109
+ import { ODESC } from "../obj/desc.js";
110
+ import { squareIsEmptyLive } from "./mon-place.js";
111
+ import { squareIsPlayerTrap, squareIsWarded, squareIsWebbed, squareRemoveAllTraps, squareTrap, } from "./trap.js";
112
+ import { groupMonsterTracking, monsterGroupLeader, monsterGroupRouse, } from "./mon-group.js";
113
+ /** enum monster_stagger. */
114
+ export const STAGGER = {
115
+ NO: 0,
116
+ CONFUSED: 1,
117
+ INNATE: 2,
118
+ };
119
+ /** mon-timed.h CONF_ERRATIC_CHANCE / STUN_MISS_CHANCE. */
120
+ const CONF_ERRATIC_CHANCE = 30;
121
+ const STUN_MISS_CHANCE = 10;
122
+ /** PRIMARY_GROUP index (monster.h). */
123
+ const PRIMARY_GROUP = 0;
124
+ /**
125
+ * dist_offsets_y / dist_offsets_x (cave.c): for each distance d (1..9), the
126
+ * offsets of every grid exactly distance d from a centre, terminated by the
127
+ * (0,0) sentinel. Copied verbatim so get_move_find_safety's ring scan order -
128
+ * and therefore its tie-break (first grid at the maximum distance wins) - match
129
+ * upstream exactly.
130
+ */
131
+ const D_OFF_Y = [
132
+ [0],
133
+ [-1, -1, -1, 0, 0, 1, 1, 1, 0],
134
+ [-1, -1, -2, -2, -2, 0, 0, 1, 1, 2, 2, 2, 0],
135
+ [-1, -1, -2, -2, -3, -3, -3, 0, 0, 1, 1, 2, 2, 3, 3, 3, 0],
136
+ [
137
+ -1, -1, -2, -2, -3, -3, -3, -3, -4, -4, -4, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4,
138
+ 4, 4, 0,
139
+ ],
140
+ [
141
+ -1, -1, -2, -2, -3, -3, -4, -4, -4, -4, -5, -5, -5, 0, 0, 1, 1, 2, 2, 3, 3,
142
+ 4, 4, 4, 4, 5, 5, 5, 0,
143
+ ],
144
+ [
145
+ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -5, -5, -6, -6, -6, 0, 0, 1, 1, 2, 2,
146
+ 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 0,
147
+ ],
148
+ [
149
+ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -5, -5, -6, -6, -6, -6, -7, -7, -7,
150
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 0,
151
+ ],
152
+ [
153
+ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -6, -6, -7, -7, -7, -7, -8,
154
+ -8, -8, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8,
155
+ 0,
156
+ ],
157
+ [
158
+ -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -7, -7, -8, -8, -8,
159
+ -8, -9, -9, -9, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8,
160
+ 8, 8, 9, 9, 9, 0,
161
+ ],
162
+ ];
163
+ const D_OFF_X = [
164
+ [0],
165
+ [-1, 0, 1, -1, 1, -1, 0, 1, 0],
166
+ [-2, 2, -1, 0, 1, -2, 2, -2, 2, -1, 0, 1, 0],
167
+ [-3, 3, -2, 2, -1, 0, 1, -3, 3, -3, 3, -2, 2, -1, 0, 1, 0],
168
+ [
169
+ -4, 4, -3, 3, -2, -3, 2, 3, -1, 0, 1, -4, 4, -4, 4, -3, 3, -2, -3, 2, 3, -1,
170
+ 0, 1, 0,
171
+ ],
172
+ [
173
+ -5, 5, -4, 4, -4, 4, -2, -3, 2, 3, -1, 0, 1, -5, 5, -5, 5, -4, 4, -4, 4, -2,
174
+ -3, 2, 3, -1, 0, 1, 0,
175
+ ],
176
+ [
177
+ -6, 6, -5, 5, -5, 5, -4, 4, -2, -3, 2, 3, -1, 0, 1, -6, 6, -6, 6, -5, 5, -5,
178
+ 5, -4, 4, -2, -3, 2, 3, -1, 0, 1, 0,
179
+ ],
180
+ [
181
+ -7, 7, -6, 6, -6, 6, -5, 5, -4, -5, 4, 5, -2, -3, 2, 3, -1, 0, 1, -7, 7, -7,
182
+ 7, -6, 6, -6, 6, -5, 5, -4, -5, 4, 5, -2, -3, 2, 3, -1, 0, 1, 0,
183
+ ],
184
+ [
185
+ -8, 8, -7, 7, -7, 7, -6, 6, -6, 6, -4, -5, 4, 5, -2, -3, 2, 3, -1, 0, 1, -8,
186
+ 8, -8, 8, -7, 7, -7, 7, -6, 6, -6, 6, -4, -5, 4, 5, -2, -3, 2, 3, -1, 0, 1,
187
+ 0,
188
+ ],
189
+ [
190
+ -9, 9, -8, 8, -8, 8, -7, 7, -7, 7, -6, 6, -4, -5, 4, 5, -2, -3, 2, 3, -1, 0,
191
+ 1, -9, 9, -9, 9, -8, 8, -8, 8, -7, 7, -7, 7, -6, 6, -4, -5, 4, 5, -2, -3, 2,
192
+ 3, -1, 0, 1, 0,
193
+ ],
194
+ ];
195
+ /** The (0,0)-terminated ring of offsets at each distance d (1..9). */
196
+ const DIST_OFFSETS = D_OFF_Y.map((ys, d) => {
197
+ const xs = D_OFF_X[d];
198
+ const ring = [];
199
+ for (let i = 0; (xs[i] ?? 0) !== 0 || (ys[i] ?? 0) !== 0; i++) {
200
+ ring.push(loc(xs[i], ys[i]));
201
+ }
202
+ return ring;
203
+ });
204
+ function noiseAt(state, grid) {
205
+ return state.chunk.noise[grid.y * state.chunk.width + grid.x] ?? 0;
206
+ }
207
+ function scentAt(state, grid) {
208
+ return state.chunk.scent[grid.y * state.chunk.width + grid.x] ?? 0;
209
+ }
210
+ /**
211
+ * monster_can_see_player (mon-move.c L92): the monster's grid is in the
212
+ * player's view, and a player covering tracks (TMD_COVERTRACKS) is unseen
213
+ * beyond max_sight / 4.
214
+ */
215
+ function monsterCanSeePlayer(mon, state) {
216
+ if (!squareIsView(state.chunk, mon.grid))
217
+ return false;
218
+ if ((state.actor.player.timed[TMD.COVERTRACKS] ?? 0) > 0 &&
219
+ mon.cdis > Math.trunc(state.z.maxSight / 4)) {
220
+ return false;
221
+ }
222
+ return true;
223
+ }
224
+ /**
225
+ * The PROJECT_SHORT projection range (project.c L370-373): max_range, quartered
226
+ * while the player covers tracks (TMD_COVERTRACKS). The port's projectable takes
227
+ * the range from the caller, so PROJECT.SHORT callers pass this.
228
+ */
229
+ export function shortRange(state) {
230
+ return (state.actor.player.timed[TMD.COVERTRACKS] ?? 0) > 0
231
+ ? Math.trunc(state.z.maxRange / 4)
232
+ : state.z.maxRange;
233
+ }
234
+ /**
235
+ * monster_near_permwall (mon-move.c L65): whether a PASS_WALL / KILL_WALL
236
+ * monster should use the flow code instead of beelining - the player is out of
237
+ * (short) projection range and the direct PROJECT_ROCK path hits a permanent
238
+ * wall before reaching the player. Draws randint0(99) for the "occasionally
239
+ * flow for a turn anyway" 5% branch, exactly at the upstream stream position.
240
+ */
241
+ export function monsterNearPermwall(mon, state) {
242
+ const c = state.chunk;
243
+ /* If player is in LOS, there's no need to go around walls. */
244
+ if (projectable(c, mon.grid, state.actor.grid, PROJECT.SHORT, shortRange(state))) {
245
+ return false;
246
+ }
247
+ /* PASS_WALL & KILL_WALL monsters occasionally flow for a turn anyway. */
248
+ if (state.rng.randint0(99) < 5)
249
+ return true;
250
+ /* Find the shortest path. */
251
+ const path = projectPath(c, state.z.maxSight, mon.grid, state.actor.grid, PROJECT.ROCK);
252
+ /* See if we can "see" the player without hitting permanent wall. */
253
+ for (const g of path) {
254
+ if (c.isPerm(g))
255
+ return true;
256
+ if (squareIsPlayer(state, g))
257
+ return false;
258
+ }
259
+ return false;
260
+ }
261
+ /** monster_can_hear: race hearing beats the local noise (minus stealth/3). */
262
+ function monsterCanHear(mon, state) {
263
+ const baseHearing = mon.race.hearing - Math.trunc(state.actor.stealth / 3);
264
+ const n = noiseAt(state, mon.grid);
265
+ if (n === 0)
266
+ return false;
267
+ return baseHearing > n;
268
+ }
269
+ /** monster_can_smell: race smell beats the local scent age. */
270
+ function monsterCanSmell(mon, state) {
271
+ const s = scentAt(state, mon.grid);
272
+ if (s === 0)
273
+ return false;
274
+ return mon.race.smell > s;
275
+ }
276
+ /** compare_monsters: -1 / 0 / 1 by (original) race experience value. */
277
+ function compareMonsters(a, b) {
278
+ const ma = (a.originalRace ?? a.race).mexp;
279
+ const mb = (b.originalRace ?? b.race).mexp;
280
+ if (ma < mb)
281
+ return -1;
282
+ if (ma > mb)
283
+ return 1;
284
+ return 0;
285
+ }
286
+ /** monster_can_kill: trample a weaker, non-unique monster (KILL_BODY). */
287
+ function monsterCanKill(state, mon, grid) {
288
+ const other = squareMonster(state, grid);
289
+ if (!other)
290
+ return true;
291
+ if (monsterIsUnique(other))
292
+ return false;
293
+ return mon.race.flags.has(RF.KILL_BODY) && compareMonsters(mon, other) > 0;
294
+ }
295
+ /** monster_can_move: swap with a weaker monster (MOVE_BODY). */
296
+ function monsterCanMoveInto(state, mon, grid) {
297
+ const other = squareMonster(state, grid);
298
+ if (!other)
299
+ return true;
300
+ return mon.race.flags.has(RF.MOVE_BODY) && compareMonsters(mon, other) > 0;
301
+ }
302
+ /**
303
+ * square_isdamaging (cave-square.c L730) && the monster lacks the feature's
304
+ * resist_flag: the shared predicate behind monster_hates_grid and
305
+ * monster_taking_terrain_damage. square_isdamaging is feat_is_fiery in 4.2.6
306
+ * (lava only), so this is chunk.isFiery gated by the feature's resistFlag.
307
+ */
308
+ function damagingTerrainHurts(state, mon, grid) {
309
+ if (!state.chunk.isFiery(grid))
310
+ return false;
311
+ return !mon.race.flags.has(state.chunk.feature(grid).resistFlag);
312
+ }
313
+ /**
314
+ * monster_hates_grid (mon-move.c L188): damaging terrain the monster can't
315
+ * survive. Draws no RNG.
316
+ */
317
+ function monsterHatesGrid(state, mon, grid) {
318
+ return damagingTerrainHurts(state, mon, grid);
319
+ }
320
+ /**
321
+ * monster_taking_terrain_damage (mon-util.c L1347): the monster is standing on
322
+ * damaging terrain it does not resist. Draws no RNG. NOTE: the actual damage
323
+ * application (monster_take_terrain_damage, mon-util.c L1327, called from
324
+ * process_monster after monster_turn) is DEFERRED - it needs mon_take_nonplayer_hit
325
+ * (monster_death / delete_monster_idx), which is not ported yet; this predicate
326
+ * only drives movement (flight / avoidance / activation).
327
+ */
328
+ function monsterTakingTerrainDamage(state, mon) {
329
+ return damagingTerrainHurts(state, mon, mon.grid);
330
+ }
331
+ /** cave->decoy is set and this grid holds it (square_isdecoyed, cave-square.c L757). */
332
+ function squareIsDecoyed(state, grid) {
333
+ const d = state.decoy;
334
+ return !!d && !locIsZero(d) && locEq(d, grid);
335
+ }
336
+ /**
337
+ * monster_is_decoyed (mon-predicate.c L308): a live decoy exists and the monster
338
+ * has line of sight to it. Draws no RNG.
339
+ */
340
+ export function monsterIsDecoyed(mon, state) {
341
+ const d = state.decoy;
342
+ if (!d || locIsZero(d))
343
+ return false;
344
+ return los(state.chunk, mon.grid, d);
345
+ }
346
+ /**
347
+ * square_remove_all_traps_of_type by trap flag: remove every trap at `grid` that
348
+ * carries `flag` (glyph of warding / web / decoy all being distinguished only by
349
+ * their tidx, which we recover from the first matching trap). Uses the existing
350
+ * trap.ts helpers (squareTrap / squareRemoveAllTraps); draws no RNG.
351
+ */
352
+ function removeTrapsWithFlag(state, grid, flag) {
353
+ for (const t of squareTrap(state, grid)) {
354
+ if (t.flags.has(flag)) {
355
+ squareRemoveAllTraps(state, grid, t.tidx);
356
+ return;
357
+ }
358
+ }
359
+ }
360
+ /**
361
+ * get_move_find_range (mon-move.c L207): set mon.minRange (flee distance) and
362
+ * mon.bestRange (preferred combat distance) - archers sit back +3, breathers
363
+ * with high innate frequency like point blank, other frequent casters sit back
364
+ * +3 (mon-move.c L287-300).
365
+ */
366
+ export function getMoveFindRange(mon, state) {
367
+ const p = state.actor.player;
368
+ const fleeRange = state.z.maxSight + state.z.fleeRange;
369
+ if ((mon.mTimed[MON_TMD.FEAR] ?? 0) ||
370
+ mon.race.flags.has(RF.FRIGHTENED)) {
371
+ mon.minRange = fleeRange;
372
+ }
373
+ else if (mon.groupInfo[PRIMARY_GROUP]?.role === MON_GROUP.BODYGUARD) {
374
+ mon.minRange = 1;
375
+ }
376
+ else {
377
+ mon.minRange = 1;
378
+ /* mon-move.c L232: taunt forces close-in movement and returns before
379
+ * level/health range heuristics or preferred-range selection. */
380
+ if ((p.timed[TMD.TAUNT] ?? 0) > 0)
381
+ return;
382
+ const pLev = p.lev;
383
+ const mLev = mon.race.level + (mon.midx & 0x08) + 25;
384
+ if (mLev + 3 < pLev) {
385
+ mon.minRange = fleeRange;
386
+ }
387
+ else if (mLev - 5 < pLev) {
388
+ const pChp = p.chp;
389
+ const pMhp = p.mhp;
390
+ const mChp = mon.hp;
391
+ const mMhp = mon.maxhp;
392
+ const pVal = pLev * pMhp + (pChp << 2);
393
+ const mVal = mLev * mMhp + (mChp << 2);
394
+ /* Strong players scare strong monsters. */
395
+ if (pVal * mMhp > mVal * pMhp)
396
+ mon.minRange = fleeRange;
397
+ }
398
+ }
399
+ if (mon.minRange < fleeRange) {
400
+ if (mon.race.flags.has(RF.NEVER_MOVE))
401
+ mon.minRange += 3;
402
+ if (mon.race.flags.has(RF.NEVER_BLOW))
403
+ mon.minRange += 3;
404
+ }
405
+ if (!(mon.minRange < fleeRange)) {
406
+ mon.minRange = fleeRange;
407
+ }
408
+ else if (mon.cdis < state.z.turnRange) {
409
+ mon.minRange = 1;
410
+ }
411
+ /* Now find the preferred range (mon-move.c L285-300). */
412
+ mon.bestRange = mon.minRange;
413
+ /* Archers are quite happy at a good distance. */
414
+ if (monsterLovesArchery(mon)) {
415
+ mon.bestRange += 3;
416
+ }
417
+ if (mon.race.freqInnate > 24) {
418
+ /* Breathers like point blank range. */
419
+ if (monsterBreathes(mon) && mon.hp > Math.trunc(mon.maxhp / 2)) {
420
+ mon.bestRange = Math.max(1, mon.bestRange);
421
+ }
422
+ }
423
+ else if (mon.race.freqSpell > 24) {
424
+ /* Other spell casters will sit back and cast. */
425
+ mon.bestRange += 3;
426
+ }
427
+ }
428
+ /**
429
+ * get_move_bodyguard (mon-move.c L309): a bodyguard stays close to its group
430
+ * leader, but takes a step that is also closer to the player when it can. Sets
431
+ * mon.target.grid and returns true on success. Draws no RNG - the scan order is
432
+ * ddgrid_ddd and the tie-break is upstream's (first closer-to-leader grid, and a
433
+ * grid that is also closer to the player short-circuits the scan).
434
+ */
435
+ export function getMoveBodyguard(mon, state) {
436
+ const leader = monsterGroupLeader(state, mon);
437
+ if (!leader)
438
+ return false;
439
+ const dist = distance(mon.grid, leader.grid);
440
+ /* If currently adjacent to the leader, we can afford a move. */
441
+ if (dist <= 1)
442
+ return false;
443
+ /* If the leader's too out of sight and far away, save yourself. */
444
+ if (!los(state.chunk, mon.grid, leader.grid) && dist > 10)
445
+ return false;
446
+ let best = loc(0, 0);
447
+ let found = false;
448
+ for (let i = 0; i < 8; i++) {
449
+ const grid = locSum(mon.grid, DDGRID_DDD[i]);
450
+ const newDist = distance(grid, leader.grid);
451
+ const charDist = distance(grid, state.actor.grid);
452
+ if (!state.chunk.inBounds(grid))
453
+ continue;
454
+ /* There's a monster blocking that we can't deal with. */
455
+ if (!monsterCanKill(state, mon, grid) && !monsterCanMoveInto(state, mon, grid)) {
456
+ continue;
457
+ }
458
+ /* There's damaging terrain. */
459
+ if (monsterHatesGrid(state, mon, grid))
460
+ continue;
461
+ /* Closer to the leader is always better. */
462
+ if (newDist < dist) {
463
+ best = grid;
464
+ found = true;
465
+ /* If there's a grid that's also closer to the player, that wins. */
466
+ if (charDist < mon.cdis)
467
+ break;
468
+ }
469
+ }
470
+ if (found) {
471
+ mon.target = { grid: best, midx: mon.target.midx };
472
+ return true;
473
+ }
474
+ return false;
475
+ }
476
+ /**
477
+ * get_move_advance: set mon.target.grid to the grid to move toward and
478
+ * return whether a good advance was found. `track` is set when the target
479
+ * came from sound/scent tracking (a one-step goal).
480
+ */
481
+ function getMoveAdvance(mon, state, track) {
482
+ const target = monsterIsDecoyed(mon, state) && state.decoy ? state.decoy : state.actor.grid;
483
+ /* Bodyguards are special. */
484
+ if (mon.groupInfo[PRIMARY_GROUP]?.role === MON_GROUP.BODYGUARD) {
485
+ if (getMoveBodyguard(mon, state))
486
+ return true;
487
+ }
488
+ /* If the monster can pass through nearby walls, do that (mon-move.c
489
+ * L416): beeline unless a permanent wall blocks the direct path. */
490
+ if (monsterPassesWalls(mon) && !monsterNearPermwall(mon, state)) {
491
+ mon.target = { grid: target, midx: mon.target.midx };
492
+ return true;
493
+ }
494
+ /* If the monster can see the player, beeline. */
495
+ if (monsterCanSeePlayer(mon, state)) {
496
+ mon.target = { grid: target, midx: mon.target.midx };
497
+ return true;
498
+ }
499
+ const baseHearing = mon.race.hearing - Math.trunc(state.actor.stealth / 3);
500
+ const currentNoise = baseHearing - noiseAt(state, mon.grid);
501
+ let best = null;
502
+ let backup = null;
503
+ /* Try to use sound, cardinal directions first (ddd order). */
504
+ if (monsterCanHear(mon, state)) {
505
+ for (let i = 0; i < 8; i++) {
506
+ const dir = DDGRID_DDD[i];
507
+ const grid = locSum(mon.grid, dir);
508
+ if (!state.chunk.inBounds(grid))
509
+ continue;
510
+ if (noiseAt(state, grid) === 0)
511
+ continue;
512
+ if (!monsterCanKill(state, mon, grid) && !monsterCanMoveInto(state, mon, grid)) {
513
+ continue;
514
+ }
515
+ if (monsterHatesGrid(state, mon, grid))
516
+ continue;
517
+ const heardNoise = baseHearing - noiseAt(state, grid);
518
+ if (heardNoise > currentNoise) {
519
+ best = grid;
520
+ break;
521
+ }
522
+ else if (heardNoise === currentNoise) {
523
+ backup = grid;
524
+ }
525
+ }
526
+ }
527
+ /* Failing sound, use scent. */
528
+ if (monsterCanSmell(mon, state) && !best) {
529
+ let bestScent = 0;
530
+ for (let i = 0; i < 8; i++) {
531
+ const dir = DDGRID_DDD[i];
532
+ const grid = locSum(mon.grid, dir);
533
+ if (!state.chunk.inBounds(grid))
534
+ continue;
535
+ const smelled = mon.race.smell - scentAt(state, grid);
536
+ if (smelled > bestScent && scentAt(state, grid) !== 0) {
537
+ bestScent = smelled;
538
+ best = grid;
539
+ }
540
+ }
541
+ }
542
+ if (best) {
543
+ mon.target = { grid: best, midx: mon.target.midx };
544
+ track.value = true;
545
+ return true;
546
+ }
547
+ else if (backup) {
548
+ mon.target = { grid: backup, midx: mon.target.midx };
549
+ track.value = true;
550
+ return true;
551
+ }
552
+ return false;
553
+ }
554
+ /** get_move_random: a random passable adjacent step, or (0,0). */
555
+ function getMoveRandom(mon, state) {
556
+ const attempts = [0, 1, 2, 3, 4, 5, 6, 7];
557
+ let nleft = 8;
558
+ while (nleft > 0) {
559
+ const itry = state.rng.randint0(nleft);
560
+ const dir = DDGRID_DDD[attempts[itry]];
561
+ const tryGrid = locSum(mon.grid, dir);
562
+ if (state.chunk.inBounds(tryGrid) &&
563
+ state.chunk.isMonsterWalkable(tryGrid) &&
564
+ !monsterHatesGrid(state, mon, tryGrid)) {
565
+ return dir;
566
+ }
567
+ const tmp = attempts[itry];
568
+ nleft--;
569
+ attempts[itry] = attempts[nleft];
570
+ attempts[nleft] = tmp;
571
+ }
572
+ return loc(0, 0);
573
+ }
574
+ /**
575
+ * get_move_choose_direction: keypad direction (as a side_dirs row index)
576
+ * from an offset, with the turn-parity tie-break exactly as upstream.
577
+ */
578
+ export function getMoveChooseDirection(offset, turn) {
579
+ let dir = 0;
580
+ const dx = offset.x;
581
+ const dy = offset.y;
582
+ const ay = Math.abs(dy);
583
+ const ax = Math.abs(dx);
584
+ if (ay > ax * 2) {
585
+ if (dy > 0) {
586
+ dir = 2;
587
+ if (dx > 0 || (dx === 0 && turn % 2 === 0))
588
+ dir += 10;
589
+ }
590
+ else {
591
+ dir = 8;
592
+ if (dx < 0 || (dx === 0 && turn % 2 === 0))
593
+ dir += 10;
594
+ }
595
+ }
596
+ else if (ax > ay * 2) {
597
+ if (dx > 0) {
598
+ dir = 6;
599
+ if (dy < 0 || (dy === 0 && turn % 2 === 0))
600
+ dir += 10;
601
+ }
602
+ else {
603
+ dir = 4;
604
+ if (dy > 0 || (dy === 0 && turn % 2 === 0))
605
+ dir += 10;
606
+ }
607
+ }
608
+ else if (dy > 0) {
609
+ if (dx > 0) {
610
+ dir = 3;
611
+ if (ay < ax || (ay === ax && turn % 2 === 0))
612
+ dir += 10;
613
+ }
614
+ else {
615
+ dir = 1;
616
+ if (ay > ax || (ay === ax && turn % 2 === 0))
617
+ dir += 10;
618
+ }
619
+ }
620
+ else {
621
+ if (dx > 0) {
622
+ dir = 9;
623
+ if (ay > ax || (ay === ax && turn % 2 === 0))
624
+ dir += 10;
625
+ }
626
+ else {
627
+ dir = 7;
628
+ if (ay < ax || (ay === ax && turn % 2 === 0))
629
+ dir += 10;
630
+ }
631
+ }
632
+ return dir;
633
+ }
634
+ /**
635
+ * get_move_find_safety (mon-move.c L545): choose a reachable grid the player
636
+ * cannot fire into (out of view) that is as far from the player as possible,
637
+ * spreading outward a distance ring at a time. Sets mon.target.grid and returns
638
+ * true on success. Pure scan - draws no RNG. The dist_offsets ring order fixes
639
+ * the tie-break: the FIRST grid at the maximum player-distance wins.
640
+ */
641
+ function getMoveFindSafety(mon, state) {
642
+ const c = state.chunk;
643
+ let gdis = 0;
644
+ let best = loc(0, 0);
645
+ for (let d = 1; d < 10; d++) {
646
+ const ring = DIST_OFFSETS[d];
647
+ for (const off of ring) {
648
+ const grid = locSum(mon.grid, off);
649
+ /* Skip illegal / walled locations. */
650
+ if (!c.inBoundsFully(grid))
651
+ continue;
652
+ if (!c.isPassable(grid))
653
+ continue;
654
+ /* Ignore too-distant grids (noise heatmap gate). */
655
+ if (noiseAt(state, grid) > noiseAt(state, mon.grid) + 2 * d)
656
+ continue;
657
+ /* Ignore damaging terrain (DEFERRED: monsterHatesGrid is false). */
658
+ if (monsterHatesGrid(state, mon, grid))
659
+ continue;
660
+ /* Check for absence of shot (more or less). */
661
+ if (!squareIsView(c, grid)) {
662
+ const dis = distance(grid, state.actor.grid);
663
+ if (dis > gdis) {
664
+ best = grid;
665
+ gdis = dis;
666
+ }
667
+ }
668
+ }
669
+ if (gdis > 0) {
670
+ mon.target = { grid: best, midx: mon.target.midx };
671
+ return true;
672
+ }
673
+ }
674
+ return false;
675
+ }
676
+ /**
677
+ * get_move_flee (mon-move.c L675): provide a swerving course toward the current
678
+ * target (a safe grid) that gives the player a wide berth. Sets mon.target.grid
679
+ * and returns true, or returns false (leaving the target as find_safety set it)
680
+ * when the monster is too far to bother. Diagonals are scanned first. Draws no
681
+ * RNG.
682
+ */
683
+ function getMoveFlee(mon, state) {
684
+ let best = loc(0, 0);
685
+ let bestScore = -1;
686
+ /* Taking damage from terrain makes moving vital; otherwise the two early-outs
687
+ * apply (player too far, or the monster can neither hear nor smell). */
688
+ if (!monsterTakingTerrainDamage(state, mon)) {
689
+ if (mon.cdis >= mon.bestRange)
690
+ return false;
691
+ if (!monsterCanHear(mon, state) && !monsterCanSmell(mon, state))
692
+ return false;
693
+ }
694
+ /* Check nearby grids, diagonals first. */
695
+ for (let i = 7; i >= 0; i--) {
696
+ const grid = locSum(mon.grid, DDGRID_DDD[i]);
697
+ if (!state.chunk.inBounds(grid))
698
+ continue;
699
+ /* Distance of this grid from our target. */
700
+ const dis = distance(grid, mon.target.grid);
701
+ /* Inversely proportional to distance, less the grid's closeness to the
702
+ * player (the noise heatmap). Integer division, as upstream. */
703
+ let score = Math.trunc(5000 / (dis + 3)) - Math.trunc(500 / (noiseAt(state, grid) + 1));
704
+ if (score < 0)
705
+ score = 0;
706
+ if (score < bestScore)
707
+ continue;
708
+ bestScore = score;
709
+ best = grid;
710
+ }
711
+ mon.target = { grid: best, midx: mon.target.midx };
712
+ return true;
713
+ }
714
+ /**
715
+ * get_move_find_hiding (mon-move.c L613): a pack monster looks for a hidden grid
716
+ * (out of the player's view but projectable from the monster) to lie in wait and
717
+ * lure the player into the open. Prefers the closest such grid that is still at
718
+ * least `min` away from the player, spreading outward a distance ring at a time.
719
+ * Sets mon.target.grid and returns true on success. Pure scan - draws no RNG.
720
+ * `gdis` persists across rings (as upstream) but the per-ring success return
721
+ * makes that moot; the dist_offsets ring order fixes the tie-break.
722
+ */
723
+ export function getMoveFindHiding(mon, state) {
724
+ const c = state.chunk;
725
+ /* square_isempty on the live cave (no player trap / web). */
726
+ const preds = {
727
+ isPlayerTrap: (g) => squareIsPlayerTrap(state, g),
728
+ isWebbed: (g) => squareIsWebbed(state, g),
729
+ isWarded: (g) => squareIsWarded(state, g),
730
+ };
731
+ /* Closest distance to get. */
732
+ const min = Math.trunc((distance(state.actor.grid, mon.grid) * 3) / 4) + 2;
733
+ let gdis = 999;
734
+ for (let d = 1; d < 10; d++) {
735
+ let best = loc(0, 0);
736
+ const ring = DIST_OFFSETS[d];
737
+ for (const off of ring) {
738
+ const grid = locSum(mon.grid, off);
739
+ /* Skip illegal / occupied locations. */
740
+ if (!c.inBoundsFully(grid))
741
+ continue;
742
+ if (!squareIsEmptyLive(state, grid, preds))
743
+ continue;
744
+ /* Check for a hidden, available grid. */
745
+ if (!squareIsView(c, grid) &&
746
+ projectable(c, mon.grid, grid, PROJECT.STOP, state.z.maxRange)) {
747
+ const dis = distance(grid, state.actor.grid);
748
+ if (dis < gdis && dis >= min) {
749
+ best = grid;
750
+ gdis = dis;
751
+ }
752
+ }
753
+ }
754
+ if (gdis < 999) {
755
+ mon.target = { grid: best, midx: mon.target.midx };
756
+ return true;
757
+ }
758
+ }
759
+ return false;
760
+ }
761
+ /**
762
+ * get_move: decide whether and where the monster wants to step. Returns the
763
+ * side_dirs row index for the movement loop. The RF_GROUP_AI pack-ambush branch
764
+ * (get_move_find_hiding) and the group-surround branch (mon-move.c L932, which
765
+ * draws randint0(8)) are both ported, so the RNG draw order matches upstream.
766
+ */
767
+ export function getMove(mon, state) {
768
+ const fleeRange = state.z.maxSight + state.z.fleeRange;
769
+ const target = monsterIsDecoyed(mon, state) && state.decoy ? state.decoy : state.actor.grid;
770
+ const groupAi = mon.race.flags.has(RF.GROUP_AI);
771
+ let grid = loc(0, 0);
772
+ const track = { value: false };
773
+ let done = false;
774
+ getMoveFindRange(mon, state);
775
+ if (getMoveAdvance(mon, state, track)) {
776
+ grid = locDiff(mon.target.grid, mon.grid);
777
+ mon.mflag.on(MFLAG.TRACKING);
778
+ }
779
+ else {
780
+ /* Try to follow someone who knows where they're going. */
781
+ const tracker = groupMonsterTracking(state, mon);
782
+ if (tracker && los(state.chunk, mon.grid, tracker.grid)) {
783
+ grid = locDiff(tracker.grid, mon.grid);
784
+ /* No longer tracking. */
785
+ mon.mflag.off(MFLAG.TRACKING);
786
+ }
787
+ else {
788
+ if (mon.mflag.has(MFLAG.TRACKING)) {
789
+ /* Keep heading to the most recent goal. */
790
+ grid = locDiff(mon.target.grid, mon.grid);
791
+ }
792
+ if (locIsZero(grid)) {
793
+ /* Try a random move and no longer track. */
794
+ grid = getMoveRandom(mon, state);
795
+ mon.mflag.off(MFLAG.TRACKING);
796
+ }
797
+ }
798
+ }
799
+ /* Monster is taking damage from terrain - flee to safety (draws no RNG:
800
+ * find_safety and flee are pure scans). */
801
+ if (monsterTakingTerrainDamage(state, mon)) {
802
+ if (getMoveFindSafety(mon, state)) {
803
+ getMoveFlee(mon, state);
804
+ grid = locDiff(mon.target.grid, mon.grid);
805
+ done = true;
806
+ }
807
+ }
808
+ /* Normal animal packs try to get the player out of corridors: if the player
809
+ * is not in the open and is healthy, find a hiding place for an ambush
810
+ * (get_move_find_hiding draws no RNG). */
811
+ if (!done && groupAi && !monsterPassesWalls(mon)) {
812
+ let open = 0;
813
+ for (let i = 0; i < 8; i++) {
814
+ const test = locSum(target, DDGRID_DDD[i]);
815
+ if (!state.chunk.inBounds(test))
816
+ continue;
817
+ if (state.chunk.isPassable(test) ||
818
+ state.chunk.sqinfoHas(test, SQUARE.ROOM)) {
819
+ open++;
820
+ }
821
+ }
822
+ const p = state.actor.player;
823
+ if (open < 5 && p.chp > Math.trunc(p.mhp / 2)) {
824
+ if (getMoveFindHiding(mon, state)) {
825
+ done = true;
826
+ grid = locDiff(mon.target.grid, mon.grid);
827
+ mon.mflag.off(MFLAG.TRACKING);
828
+ }
829
+ }
830
+ }
831
+ /* Not hiding and monster is afraid. */
832
+ if (!done && mon.minRange === fleeRange) {
833
+ /* Try to find a safe place. */
834
+ if (getMoveFindSafety(mon, state)) {
835
+ /* Set a course for the safe place (flee's return is ignored: on a
836
+ * false early-out the target stays as find_safety set it). */
837
+ getMoveFlee(mon, state);
838
+ grid = locDiff(mon.target.grid, mon.grid);
839
+ }
840
+ else {
841
+ /* Just leg it away from the player. */
842
+ grid = locDiff(loc(0, 0), grid);
843
+ }
844
+ /* No longer tracking. */
845
+ mon.mflag.off(MFLAG.TRACKING);
846
+ done = true;
847
+ }
848
+ /* Monster groups try to surround the player if they're in sight
849
+ * (mon-move.c L932). When not already adjacent (cdis > 1) it draws
850
+ * randint0(8) to pick a pseudo-random starting direction, then fills the
851
+ * first empty grid near the player from there; if none is empty grid1 keeps
852
+ * the last computed offset (matching the C loop's fall-through). */
853
+ if (!done && groupAi && squareIsView(state.chunk, mon.grid)) {
854
+ let grid1 = mon.target.grid;
855
+ if (mon.cdis > 1) {
856
+ const preds = {
857
+ isPlayerTrap: (g) => squareIsPlayerTrap(state, g),
858
+ isWebbed: (g) => squareIsWebbed(state, g),
859
+ isWarded: (g) => squareIsWarded(state, g),
860
+ };
861
+ const tmp = state.rng.randint0(8);
862
+ for (let i = 0; i < 8; i++) {
863
+ grid1 = locSum(target, DDGRID_DDD[(tmp + i) % 8]);
864
+ if (!squareIsEmptyLive(state, grid1, preds))
865
+ continue;
866
+ break;
867
+ }
868
+ }
869
+ grid = locDiff(grid1, mon.grid);
870
+ }
871
+ if (locIsZero(grid))
872
+ return { move: false, dir: 0, tracking: track.value };
873
+ return {
874
+ move: true,
875
+ dir: getMoveChooseDirection(grid, state.turn),
876
+ tracking: track.value,
877
+ };
878
+ }
879
+ /**
880
+ * monster_turn_should_stagger: whether the monster steps at random this turn
881
+ * (confusion staggers, then the cumulative RAND_25 / RAND_50 chances).
882
+ */
883
+ export function monsterTurnShouldStagger(mon, state) {
884
+ let chance = 0;
885
+ let confLevel = monsterEffectLevel(mon, MON_TMD.CONF);
886
+ while (confLevel) {
887
+ let accuracy = 100 - chance;
888
+ accuracy *= 100 - CONF_ERRATIC_CHANCE;
889
+ accuracy = Math.trunc(accuracy / 100);
890
+ chance = 100 - accuracy;
891
+ confLevel--;
892
+ }
893
+ const confusedChance = chance;
894
+ if (mon.race.flags.has(RF.RAND_25))
895
+ chance += 25;
896
+ if (mon.race.flags.has(RF.RAND_50))
897
+ chance += 50;
898
+ const roll = state.rng.randint0(100);
899
+ if (roll < confusedChance)
900
+ return STAGGER.CONFUSED;
901
+ return roll < chance ? STAGGER.INNATE : STAGGER.NO;
902
+ }
903
+ /** square_issecretdoor: a door still disguised as rock (cave-square.c L304). */
904
+ function squareIsSecretDoor(state, grid) {
905
+ const f = state.chunk.feature(grid).flags;
906
+ return f.has(TF.DOOR_ANY) && f.has(TF.ROCK);
907
+ }
908
+ /** square_destroy_wall (cave-square.c L1419): turn a wall to floor. */
909
+ function squareDestroyWall(state, grid) {
910
+ state.chunk.setFeat(grid, FEAT.FLOOR);
911
+ }
912
+ /** square_open_door (cave-square.c L1351): remove the lock, open the door. */
913
+ function squareOpenDoor(state, grid) {
914
+ state.removeDoorLock?.(grid);
915
+ state.chunk.setFeat(grid, FEAT.OPEN);
916
+ }
917
+ /** square_smash_door (cave-square.c L1367): remove the lock, break the door. */
918
+ function squareSmashDoor(state, grid) {
919
+ state.removeDoorLock?.(grid);
920
+ state.chunk.setFeat(grid, FEAT.BROKEN);
921
+ }
922
+ /**
923
+ * square_smash_wall (cave-square.c L1424): reduce the wall and much of what is
924
+ * next to it to floor. Each adjacent granite / quartz / magma grid gets a
925
+ * survival roll (one_in_ 4 / 10 / 20) - the RNG draws happen in ddgrid_ddd
926
+ * order, exactly once per mineral neighbour. (Decoy destruction on adjacent
927
+ * floors is DEFERRED and draws no RNG.)
928
+ */
929
+ function squareSmashWall(state, grid) {
930
+ const c = state.chunk;
931
+ c.setFeat(grid, FEAT.FLOOR);
932
+ for (let i = 0; i < 8; i++) {
933
+ const adj = locSum(grid, DDGRID_DDD[i]);
934
+ if (!c.inBoundsFully(adj))
935
+ continue;
936
+ if (c.isPerm(adj))
937
+ continue;
938
+ /* Ignore floors (adjacent-decoy destruction DEFERRED). */
939
+ if (c.isFloor(adj))
940
+ continue;
941
+ /* Give this grid a chance to survive. */
942
+ if ((c.isGranite(adj) && state.rng.oneIn(4)) ||
943
+ (c.isQuartz(adj) && state.rng.oneIn(10)) ||
944
+ (c.isMagma(adj) && state.rng.oneIn(20))) {
945
+ continue;
946
+ }
947
+ c.setFeat(adj, FEAT.FLOOR);
948
+ }
949
+ }
950
+ /**
951
+ * monster_slightly_stun_by_move (mon-move.c L1127): a confused monster that
952
+ * bumbles into something may lightly stun itself (one_in_(3), then a normal
953
+ * mon_inc_timed which itself may draw the STUN resist save).
954
+ */
955
+ function monsterSlightlyStunByMove(mon, state) {
956
+ if ((mon.mTimed[MON_TMD.STUN] ?? 0) < 5 && state.rng.oneIn(3)) {
957
+ monIncTimed(state.rng, mon, MON_TMD.STUN, 3, 0);
958
+ }
959
+ }
960
+ /**
961
+ * monster_turn_can_move (mon-move.c L1141): whether the monster can move
962
+ * through `next`, opening / bashing doors or smashing / boring walls in the
963
+ * way. `did` is set true when the monster spent its turn on a terrain action
964
+ * (or a confused bump) even though it did not move - the caller keeps the
965
+ * "can move here" result distinct from "did the terrain action".
966
+ */
967
+ /**
968
+ * monster_desc for a movement/behaviour message: m_name as upstream builds it
969
+ * (MDESC_CAPITAL | MDESC_IND_HID | MDESC_COMMA), e.g. "The kobold". Pure, no RNG.
970
+ */
971
+ function monMoveName(mon) {
972
+ return monsterDesc(mon, MDESC.CAPITAL | MDESC.IND_HID | MDESC.COMMA);
973
+ }
974
+ /**
975
+ * monster_display_confused_move_msg (mon-move.c L1111): a confused monster that
976
+ * bumps an obstacle stumbles - "%s %s." with the terrain's confused_msg, or
977
+ * "stumbles" when the feature defines none. Only shown for a monster both
978
+ * visible and in view. Draws no RNG.
979
+ */
980
+ function displayConfusedMoveMsg(mon, state, next) {
981
+ if (monsterIsVisible(mon) && monsterIsInView(mon)) {
982
+ const m = state.chunk.feature(next).confusedMsg;
983
+ state.msg?.(`${monMoveName(mon)} ${m || "stumbles"}.`);
984
+ }
985
+ }
986
+ function monsterTurnCanMove(mon, state, next, confused, did) {
987
+ const lore = getLore(state.lore, mon.race);
988
+ /* Always allow an attack upon the player or decoy. */
989
+ if (squareIsPlayer(state, next) || squareIsDecoyed(state, next))
990
+ return true;
991
+ /* Dangerous terrain in the way (monsterHatesGrid is DEFERRED: false). */
992
+ if (!confused && monsterHatesGrid(state, mon, next))
993
+ return false;
994
+ /* Floor is open? */
995
+ if (state.chunk.isPassable(next))
996
+ return true;
997
+ /* Permanent wall in the way. */
998
+ if (state.chunk.isPerm(next)) {
999
+ if (confused) {
1000
+ did.value = true;
1001
+ displayConfusedMoveMsg(mon, state, next);
1002
+ monsterSlightlyStunByMove(mon, state);
1003
+ }
1004
+ return false;
1005
+ }
1006
+ /* Normal wall, door, or secret door in the way - learn kill / pass-wall. */
1007
+ if (monsterIsVisible(mon)) {
1008
+ lore.flags.on(RF.PASS_WALL);
1009
+ lore.flags.on(RF.KILL_WALL);
1010
+ lore.flags.on(RF.SMASH_WALL);
1011
+ }
1012
+ if (mon.race.flags.has(RF.PASS_WALL)) {
1013
+ return true;
1014
+ }
1015
+ else if (mon.race.flags.has(RF.SMASH_WALL)) {
1016
+ squareSmashWall(state, next);
1017
+ return true;
1018
+ }
1019
+ else if (mon.race.flags.has(RF.KILL_WALL)) {
1020
+ squareDestroyWall(state, next);
1021
+ return true;
1022
+ }
1023
+ else if (state.chunk.isClosedDoor(next) || squareIsSecretDoor(state, next)) {
1024
+ /* Don't allow a confused move to open a door. */
1025
+ const canOpen = mon.race.flags.has(RF.OPEN_DOOR) && !confused;
1026
+ /* During a confused move, a monster only bashes sometimes. */
1027
+ const canBash = mon.race.flags.has(RF.BASH_DOOR) && (!confused || state.rng.oneIn(3));
1028
+ let willBash = false;
1029
+ /* Take a turn. */
1030
+ if (canOpen || canBash)
1031
+ did.value = true;
1032
+ /* Learn about door abilities. */
1033
+ if (!confused && monsterIsVisible(mon)) {
1034
+ lore.flags.on(RF.OPEN_DOOR);
1035
+ lore.flags.on(RF.BASH_DOOR);
1036
+ }
1037
+ /* If creature can open or bash doors, make a choice. */
1038
+ if (canOpen) {
1039
+ /* Sometimes bash anyway (impatient). */
1040
+ if (canBash)
1041
+ willBash = state.rng.oneIn(2);
1042
+ }
1043
+ else if (canBash) {
1044
+ /* Only choice. */
1045
+ willBash = true;
1046
+ }
1047
+ else {
1048
+ /* Door is an insurmountable obstacle. */
1049
+ if (confused) {
1050
+ did.value = true;
1051
+ displayConfusedMoveMsg(mon, state, next);
1052
+ monsterSlightlyStunByMove(mon, state);
1053
+ }
1054
+ return false;
1055
+ }
1056
+ /* Now outcome depends on type of door. */
1057
+ const lockPower = state.doorLockPower?.(next) ?? 0;
1058
+ if (lockPower > 0) {
1059
+ /* Locked door -- test monster strength against door strength. */
1060
+ if (state.rng.randint0(Math.trunc(mon.hp / 10)) > lockPower) {
1061
+ state.msg?.(willBash
1062
+ ? `${monMoveName(mon)} slams against the door.`
1063
+ : `${monMoveName(mon)} fiddles with the lock.`);
1064
+ /* Reduce the power of the door by one. */
1065
+ state.setDoorLock?.(next, lockPower - 1);
1066
+ }
1067
+ if (confused) {
1068
+ if (monsterIsVisible(mon))
1069
+ lore.flags.on(RF.BASH_DOOR);
1070
+ monsterSlightlyStunByMove(mon, state);
1071
+ }
1072
+ }
1073
+ else {
1074
+ /* Closed or secret door -- always open or bash. */
1075
+ if (willBash) {
1076
+ squareSmashDoor(state, next);
1077
+ /* mon-move.c L1269-1270: the burst is heard everywhere, then disturb()
1078
+ * stops the player running / resting. Neither draws RNG. */
1079
+ state.msg?.("You hear a door burst open!");
1080
+ disturb(state);
1081
+ if (confused) {
1082
+ if (monsterIsVisible(mon))
1083
+ lore.flags.on(RF.BASH_DOOR);
1084
+ monsterSlightlyStunByMove(mon, state);
1085
+ }
1086
+ /* Fall into doorway. */
1087
+ return true;
1088
+ }
1089
+ else {
1090
+ squareOpenDoor(state, next);
1091
+ }
1092
+ }
1093
+ }
1094
+ else if (confused) {
1095
+ did.value = true;
1096
+ displayConfusedMoveMsg(mon, state, next);
1097
+ monsterSlightlyStunByMove(mon, state);
1098
+ }
1099
+ return false;
1100
+ }
1101
+ /** monster_turn_try_push: trample or swap a blocking monster. */
1102
+ function monsterTurnTryPush(mon, state, next) {
1103
+ const killOk = monsterCanKill(state, mon, next);
1104
+ const moveOk = monsterCanMoveInto(state, mon, next) && state.chunk.isPassable(mon.grid);
1105
+ if (!killOk && !moveOk)
1106
+ return false;
1107
+ /* Reveal a camouflaged blocker (mon-move.c L1352) before it is potentially
1108
+ * trampled. */
1109
+ const victim = squareMonster(state, next);
1110
+ if (victim && monsterIsCamouflaged(victim)) {
1111
+ state.becomeAware?.(victim);
1112
+ }
1113
+ /* Note if visible (mon-move.c L1355-1358): "%s tramples over / pushes past
1114
+ * %s." n_name is monster_desc(mon1, MDESC_IND_HID). No RNG. */
1115
+ if (victim && monsterIsVisible(mon) && monsterIsInView(mon)) {
1116
+ state.msg?.(`${monMoveName(mon)} ${killOk ? "tramples over" : "pushes past"} ` +
1117
+ `${monsterDesc(victim, MDESC.IND_HID)}.`);
1118
+ }
1119
+ if (killOk) {
1120
+ if (victim) {
1121
+ /* mon-move.c L1360: delete_monster_idx clears groups, targets,
1122
+ * tracking, occupancy and the held/drop bookkeeping seam. */
1123
+ deleteMonster(state, victim.midx);
1124
+ }
1125
+ }
1126
+ monsterSwap(state, mon.grid, next);
1127
+ return true;
1128
+ }
1129
+ /**
1130
+ * monster_turn_multiply (mon-move.c L1025): every monster is checked here so
1131
+ * the RF_MULTIPLY lore is learnt when the crowd roll passes; only breeders that
1132
+ * find room actually reproduce. Returns true if reproduction spent the turn.
1133
+ *
1134
+ * RNG order is exact: the level cap and arena gate draw nothing, then the 3x3
1135
+ * neighbour count (k, which always includes the monster itself so k >= 1), then
1136
+ * one_in_(k * repro_monster_rate) - and only on a passing roll does the breeder
1137
+ * gate and multiply_monster (via the state.monsterMultiply hook) run.
1138
+ */
1139
+ export function monsterTurnMultiply(mon, state) {
1140
+ /* Too many breeders on the level already. */
1141
+ if ((state.numRepro ?? 0) >= state.z.reproMonsterMax)
1142
+ return false;
1143
+ /* No breeding in single combat. */
1144
+ if (state.arenaLevel)
1145
+ return false;
1146
+ /* Count the adjacent monsters (the 3x3 includes the monster itself). */
1147
+ let k = 0;
1148
+ for (let y = mon.grid.y - 1; y <= mon.grid.y + 1; y++) {
1149
+ for (let x = mon.grid.x - 1; x <= mon.grid.x + 1; x++) {
1150
+ const g = loc(x, y);
1151
+ if (state.chunk.inBounds(g) && state.chunk.mon(g) > 0)
1152
+ k++;
1153
+ }
1154
+ }
1155
+ /* Multiply slower in crowded areas. */
1156
+ if (k < 4 && (k === 0 || state.rng.oneIn(k * state.z.reproMonsterRate))) {
1157
+ /* Successful breeding attempt, learn about that now. */
1158
+ const lore = getLore(state.lore, mon.race);
1159
+ loreLearnFlagIfVisible(lore, mon, RF.MULTIPLY);
1160
+ /* Leave now if not a breeder. */
1161
+ if (!mon.race.flags.has(RF.MULTIPLY))
1162
+ return false;
1163
+ /* Try to multiply. */
1164
+ if (state.monsterMultiply?.(mon)) {
1165
+ /* Make a sound. */
1166
+ if (monsterIsVisible(mon))
1167
+ state.sound?.(MSG.MULTIPLY);
1168
+ /* Multiplying takes energy. */
1169
+ return true;
1170
+ }
1171
+ }
1172
+ return false;
1173
+ }
1174
+ /**
1175
+ * monster_turn_grab_objects (mon-move.c L1374): pick up (TAKE_ITEM) or crush
1176
+ * (KILL_ITEM) the floor objects at `next`. Gold, mimicked objects and artifacts
1177
+ * are left alone. Draws no RNG. The lore learn, the react_to_slay pickup-safety
1178
+ * check and the seen/ignore message gating are handled as noted (react_to_slay
1179
+ * is DEFERRED - it draws no RNG; messages ride presentation).
1180
+ */
1181
+ function monsterTurnGrabObjects(mon, state, next) {
1182
+ const lore = getLore(state.lore, mon.race);
1183
+ const visible = monsterIsVisible(mon);
1184
+ /* Learn about item pickup behaviour. */
1185
+ for (const obj of floorPile(state, next)) {
1186
+ if (!tvalIsMoney(obj.tval) && visible) {
1187
+ lore.flags.on(RF.TAKE_ITEM);
1188
+ lore.flags.on(RF.KILL_ITEM);
1189
+ break;
1190
+ }
1191
+ }
1192
+ /* Abort if can't pick up / kill. */
1193
+ if (!mon.race.flags.has(RF.TAKE_ITEM) &&
1194
+ !mon.race.flags.has(RF.KILL_ITEM)) {
1195
+ return;
1196
+ }
1197
+ /* Take or kill objects on the floor (snapshot: the pile is mutated). */
1198
+ for (const obj of [...floorPile(state, next)]) {
1199
+ /* Skip gold. */
1200
+ if (tvalIsMoney(obj.tval))
1201
+ continue;
1202
+ /* Skip mimicked objects. */
1203
+ if (obj.mimickingMIdx)
1204
+ continue;
1205
+ /* o_name (mon-move.c L1416) is object_desc(PREFIX|FULL); computed lazily so
1206
+ * an unseen pickup/crush - the common case - never pays for the describe.
1207
+ * !ignore_item_ok(player, obj): a message is suppressed for items the player
1208
+ * has chosen to ignore. state.isIgnored is the wired equivalent; absent
1209
+ * (worldless), nothing is ignored so the message shows. */
1210
+ const oName = () => describeObject(state, obj, ODESC.PREFIX | ODESC.FULL);
1211
+ const notIgnored = !(state.isIgnored?.(obj) ?? false);
1212
+ /* Artifacts are "safe" - a monster cannot pick them up; so are objects
1213
+ * that would hurt the monster (react_to_slay, mon-move.c L1420). */
1214
+ const safe = (obj.artifact ? true : false) || reactToSlay(obj, mon, state.slays);
1215
+ if (safe) {
1216
+ /* Only give a message for "take_item" (mon-move.c L1424-1432). */
1217
+ if (mon.race.flags.has(RF.TAKE_ITEM) &&
1218
+ visible &&
1219
+ squareIsView(state.chunk, next) &&
1220
+ notIgnored) {
1221
+ state.msg?.(`${monMoveName(mon)} tries to pick up ${oName()}, but fails.`);
1222
+ }
1223
+ }
1224
+ else if (mon.race.flags.has(RF.TAKE_ITEM)) {
1225
+ /* Pick it up: move the floor object into the monster's held pile. The
1226
+ * player-cave placeholder copy rides the knowledge subsystem (DEFERRED);
1227
+ * here the object simply leaves the floor and joins the monster. */
1228
+ if (floorExcise(state, next, obj)) {
1229
+ monsterCarry(mon.heldObj, obj, mon.midx);
1230
+ /* Describe observable situations (mon-move.c L1452-1454). */
1231
+ if (squareIsSeen(state.chunk, next) && notIgnored) {
1232
+ state.msg?.(`${monMoveName(mon)} picks up ${oName()}.`);
1233
+ }
1234
+ }
1235
+ }
1236
+ else {
1237
+ /* Crush it (mon-move.c L1466-1468). */
1238
+ if (squareIsSeen(state.chunk, next) && notIgnored) {
1239
+ state.msg?.(`${monMoveName(mon)} crushes ${oName()}.`, MSG.DESTROY);
1240
+ state.sound?.(MSG.DESTROY);
1241
+ }
1242
+ floorExcise(state, next, obj);
1243
+ }
1244
+ }
1245
+ }
1246
+ /**
1247
+ * monster_turn_attack_glyph (mon-move.c L1299): a monster on a warded grid tries
1248
+ * to break the glyph of warding. Draws exactly one randint1(glyph_hardness); on
1249
+ * a roll below the monster's level the ward breaks (the glyph trap is removed)
1250
+ * and it returns true, else the ward holds and it returns false. The
1251
+ * "rune of protection is broken!" message is UI (DEFERRED, no RNG).
1252
+ */
1253
+ function monsterTurnAttackGlyph(mon, state, next) {
1254
+ if (state.rng.randint1(state.z.glyphHardness) < mon.race.level) {
1255
+ /* Describe observable breakage (mon-move.c L1308). */
1256
+ if (squareIsSeen(state.chunk, next)) {
1257
+ state.msg?.("The rune of protection is broken!");
1258
+ }
1259
+ removeTrapsWithFlag(state, next, TRF.GLYPH);
1260
+ return true;
1261
+ }
1262
+ return false;
1263
+ }
1264
+ /**
1265
+ * monster_turn: the monster acts. A ranged attack (spell / breath) is attempted
1266
+ * first through the injected state.monsterCast hook (make_ranged_attack, wired by
1267
+ * game/mon-ranged.ts installMonsterCasting); when it spends the turn we stop
1268
+ * here, exactly as upstream's `if (make_ranged_attack(mon)) return;`.
1269
+ * Item pickup, group behaviour and lore are partially DEFERRED (see the module
1270
+ * header); this ports the movement/attack core plus web/glyph/decoy handling.
1271
+ */
1272
+ export function monsterTurn(mon, state) {
1273
+ /* W2.2 mod seam: a trusted plugin may take this monster's turn over entirely.
1274
+ * Absent (the default) this is a no-op and the ported AI runs unchanged. The
1275
+ * hook runs before any AI RNG is drawn, so a mod that skips the turn leaves
1276
+ * the seeded stream exactly where a "do nothing" monster would. */
1277
+ if (state.monsterTurnHook?.(mon, state))
1278
+ return;
1279
+ let didSomething = false;
1280
+ /* If we're in a web, deal with that (mon-move.c L1519). Draws no RNG. */
1281
+ if (squareIsWebbed(state, mon.grid)) {
1282
+ const lore = getLore(state.lore, mon.race);
1283
+ if (monsterIsVisible(mon)) {
1284
+ lore.flags.on(RF.CLEAR_WEB);
1285
+ lore.flags.on(RF.PASS_WEB);
1286
+ }
1287
+ /* If we can pass, no need to clear. */
1288
+ if (!mon.race.flags.has(RF.PASS_WEB)) {
1289
+ if (monsterIsVisible(mon)) {
1290
+ lore.flags.on(RF.PASS_WALL);
1291
+ lore.flags.on(RF.KILL_WALL);
1292
+ }
1293
+ if (mon.race.flags.has(RF.PASS_WALL)) {
1294
+ /* Insubstantial monsters go right through. */
1295
+ }
1296
+ else if (monsterPassesWalls(mon)) {
1297
+ /* If you can destroy a wall, you can destroy a web. */
1298
+ removeTrapsWithFlag(state, mon.grid, TRF.WEB);
1299
+ }
1300
+ else if (mon.race.flags.has(RF.CLEAR_WEB)) {
1301
+ /* Clearing costs a turn. */
1302
+ removeTrapsWithFlag(state, mon.grid, TRF.WEB);
1303
+ return;
1304
+ }
1305
+ else {
1306
+ /* Stuck. */
1307
+ return;
1308
+ }
1309
+ }
1310
+ }
1311
+ /* Let other group monsters know about the player. */
1312
+ monsterGroupRouse(state, mon);
1313
+ /* Try to multiply - this can use up a turn (mon-move.c L1564, BEFORE the
1314
+ * ranged attack, so its cap / chance rolls precede make_ranged_attack in the
1315
+ * RNG stream). */
1316
+ if (monsterTurnMultiply(mon, state))
1317
+ return;
1318
+ /* Attempt a ranged attack (spell / breath) before moving. */
1319
+ if (state.monsterCast?.(mon, state))
1320
+ return;
1321
+ const stagger = monsterTurnShouldStagger(mon, state);
1322
+ let dir = 0;
1323
+ let tracking = false;
1324
+ if (stagger === STAGGER.NO) {
1325
+ const decision = getMove(mon, state);
1326
+ if (!decision.move)
1327
+ return;
1328
+ dir = decision.dir;
1329
+ tracking = decision.tracking;
1330
+ }
1331
+ for (let i = 0; i < 5 && !didSomething; i++) {
1332
+ const d = stagger !== STAGGER.NO
1333
+ ? DDD[state.rng.randint0(8)]
1334
+ : SIDE_DIRS[dir]?.[i];
1335
+ const next = locSum(mon.grid, DDGRID[d]);
1336
+ /* Tracking monsters commit to their best direction. */
1337
+ if (i > 0 &&
1338
+ stagger === STAGGER.NO &&
1339
+ !squareIsView(state.chunk, mon.grid) &&
1340
+ tracking) {
1341
+ break;
1342
+ }
1343
+ if (!state.chunk.inBounds(next))
1344
+ continue;
1345
+ /* "can move here" (return) is kept distinct from "did the terrain action"
1346
+ * (canDid) which spends the turn even when the monster does not step. */
1347
+ const canDid = { value: false };
1348
+ const canMove = monsterTurnCanMove(mon, state, next, stagger === STAGGER.CONFUSED, canDid);
1349
+ if (canDid.value)
1350
+ didSomething = true;
1351
+ if (!canMove)
1352
+ continue;
1353
+ /* Try to break the glyph if there is one. This can happen multiple times
1354
+ * per turn because failure does not break the loop. A decoy grid also
1355
+ * carries the GLYPH trap flag, so exclude it here (it is handled next). */
1356
+ if (squareIsWarded(state, next) &&
1357
+ !squareIsDecoyed(state, next) &&
1358
+ !monsterTurnAttackGlyph(mon, state, next)) {
1359
+ continue;
1360
+ }
1361
+ /* Break a decoy if there is one. */
1362
+ if (squareIsDecoyed(state, next)) {
1363
+ const lore = getLore(state.lore, mon.race);
1364
+ if (monsterIsVisible(mon))
1365
+ lore.flags.on(RF.NEVER_BLOW);
1366
+ /* Some monsters never attack. */
1367
+ if (mon.race.flags.has(RF.NEVER_BLOW))
1368
+ continue;
1369
+ /* Destroy the decoy (square_destroy_decoy, cave-square.c L1402): remove
1370
+ * the decoy trap and clear cave->decoy. The "decoy is destroyed!" message
1371
+ * is UI (DEFERRED, no RNG). */
1372
+ removeTrapsWithFlag(state, next, TRF.GLYPH);
1373
+ state.decoy = null;
1374
+ didSomething = true;
1375
+ break;
1376
+ }
1377
+ if (squareIsPlayer(state, next)) {
1378
+ if (mon.race.flags.has(RF.NEVER_BLOW))
1379
+ continue;
1380
+ const result = monMeleeAttack(state.rng, mon, state.actor.player, state.actor.defense, state.monBlowEnv ? { env: state.monBlowEnv(mon) } : {});
1381
+ /* Being attacked teaches the to-armor rune (mon-attack.c L530). Its
1382
+ * player_learn_rune tail-calls update_player_object_knowledge (L1373), so
1383
+ * sweep carried/floor objects for any awareness the new rune completes. */
1384
+ equipLearnOnDefend(state.actor.player, state.runeEnv);
1385
+ updatePlayerObjectKnowledge(state);
1386
+ if (result.playerDied || state.actor.player.chp < 0) {
1387
+ state.isDead = true;
1388
+ state.playing = false;
1389
+ }
1390
+ /* Analyze "visible" monsters only: count obvious or damaging blows
1391
+ * (mon-attack.c L727), notice the cause of death, refresh lore. */
1392
+ const lore = getLore(state.lore, mon.race);
1393
+ if (monsterIsVisible(mon)) {
1394
+ result.blows.forEach((blow, i) => {
1395
+ if (blow.obvious || blow.damage || (lore.blowTimesSeen[i] ?? 0) > 10) {
1396
+ if ((lore.blowTimesSeen[i] ?? 0) < 255)
1397
+ lore.blowTimesSeen[i]++;
1398
+ }
1399
+ });
1400
+ }
1401
+ if (state.isDead)
1402
+ loreCountU16(lore, "deaths");
1403
+ loreUpdate(mon.race, lore);
1404
+ didSomething = true;
1405
+ break;
1406
+ }
1407
+ if (mon.race.flags.has(RF.NEVER_MOVE))
1408
+ return;
1409
+ if (squareMonster(state, next)) {
1410
+ didSomething = monsterTurnTryPush(mon, state, next);
1411
+ }
1412
+ else {
1413
+ monsterSwap(state, mon.grid, next);
1414
+ didSomething = true;
1415
+ }
1416
+ /* Scan all objects in the grid, if we reached it. */
1417
+ if (squareMonster(state, next) === mon) {
1418
+ monsterTurnGrabObjects(mon, state, next);
1419
+ }
1420
+ }
1421
+ /* Possible disturb (mon-move.c L1661-1670): a visible monster that acted in
1422
+ * the player's view stops the player running / resting, gated by the
1423
+ * disturb_near option (shipped default true). The did_something NEVER_MOVE
1424
+ * lore learn rides the lore layer; disturb draws no RNG. */
1425
+ if (didSomething &&
1426
+ monsterIsVisible(mon) &&
1427
+ mon.mflag.has(MFLAG.VIEW) &&
1428
+ (state.options?.get("disturb_near") ?? true)) {
1429
+ disturb(state);
1430
+ }
1431
+ /* Out of options - monster is paralysed by fear (converts fear to hold). */
1432
+ if (!didSomething && (mon.mTimed[MON_TMD.FEAR] ?? 0)) {
1433
+ const amount = mon.mTimed[MON_TMD.FEAR] ?? 0;
1434
+ const sink = monsterTimedMessage(state);
1435
+ monClearTimed(state.rng, mon, MON_TMD.FEAR, MON_TMD_FLG_NOMESSAGE);
1436
+ monIncTimed(state.rng, mon, MON_TMD.HOLD, amount, MON_TMD_FLG_NOTIFY, sink);
1437
+ }
1438
+ /* If we see an unaware monster do something, become aware of it
1439
+ * (mon-move.c L1680). */
1440
+ if (didSomething && monsterIsCamouflaged(mon)) {
1441
+ state.becomeAware?.(mon);
1442
+ }
1443
+ }
1444
+ /**
1445
+ * monster_reduce_sleep (mon-move.c L1729): wake a monster (or reduce its sleep)
1446
+ * from player noise. The notice roll is drawn unconditionally (matching
1447
+ * upstream), then aggravation is checked first: an aggravating player wakes the
1448
+ * monster outright via monster_wake (which draws its own randint0(100)); only
1449
+ * otherwise does the noise-notice reduction run.
1450
+ */
1451
+ function monsterTimedMessage(state) {
1452
+ return (mon, note) => {
1453
+ const text = formatMonsterMessageByName(mon, note);
1454
+ if (text)
1455
+ state.msg?.(text);
1456
+ };
1457
+ }
1458
+ function monsterReduceSleep(mon, state) {
1459
+ const stealth = state.actor.stealth;
1460
+ const playerNoise = Math.pow(2, 30 - stealth);
1461
+ const notice = state.rng.randint0(1024);
1462
+ const aggravate = state.playerState?.flags.has(OF.AGGRAVATE) ?? false;
1463
+ if (aggravate) {
1464
+ /* Wake the monster, make it aware. */
1465
+ monsterWake(state.rng, mon, false, 100);
1466
+ /* Notify the player if aware (mon-move.c L1748-1750). equip_learn_flag(
1467
+ * OF_AGGRAVATE) is lore (DEFERRED). No RNG. */
1468
+ if (monsterIsObvious(mon)) {
1469
+ state.msg?.(`${monMoveName(mon)} wakes up.`);
1470
+ }
1471
+ }
1472
+ else if (notice * notice * notice <= playerNoise) {
1473
+ let sleepReduction = 1;
1474
+ const localNoise = noiseAt(state, mon.grid);
1475
+ if (localNoise > 0 && localNoise < 50) {
1476
+ sleepReduction = Math.trunc(100 / localNoise);
1477
+ }
1478
+ monDecTimed(state.rng, mon, MON_TMD.SLEEP, sleepReduction, MON_TMD_FLG_NOTIFY, monsterTimedMessage(state));
1479
+ const next = mon.mTimed[MON_TMD.SLEEP] ?? 0;
1480
+ /* Update knowledge (mon-move.c L1771): a watched sleeper that stirs
1481
+ * is "ignored", one that wakes is "woken". */
1482
+ if (monsterIsObvious(mon)) {
1483
+ const lore = getLore(state.lore, mon.race);
1484
+ loreCountU8(lore, next > 0 ? "ignore" : "wake");
1485
+ loreUpdate(mon.race, lore);
1486
+ }
1487
+ }
1488
+ }
1489
+ /**
1490
+ * process_monster_timed: decrement timed effects, wake sleepers. Returns
1491
+ * true if the monster skips its turn (asleep, held, commanded, or a stunned
1492
+ * miss). Message plumbing and lore are DEFERRED.
1493
+ */
1494
+ export function processMonsterTimed(mon, state) {
1495
+ if (mon.mTimed[MON_TMD.SLEEP] ?? 0) {
1496
+ monsterReduceSleep(mon, state);
1497
+ return true;
1498
+ }
1499
+ if (state.rng.oneIn(10) && mon.mflag.has(MFLAG.ACTIVE)) {
1500
+ mon.mflag.on(MFLAG.AWARE);
1501
+ }
1502
+ const sink = monsterTimedMessage(state);
1503
+ const shape = {
1504
+ change: () => false,
1505
+ revert: (m) => monsterRevertShape(state, m),
1506
+ };
1507
+ /* mon-move.c L1800-1826: flag-0 decrements precede the notifying
1508
+ * stun/confusion/shape decrements, all through mon_dec_timed. */
1509
+ for (const idx of [MON_TMD.FAST, MON_TMD.SLOW, MON_TMD.HOLD, MON_TMD.DISEN]) {
1510
+ if ((mon.mTimed[idx] ?? 0) > 0)
1511
+ monDecTimed(state.rng, mon, idx, 1);
1512
+ }
1513
+ for (const idx of [MON_TMD.STUN, MON_TMD.CONF]) {
1514
+ if ((mon.mTimed[idx] ?? 0) > 0) {
1515
+ monDecTimed(state.rng, mon, idx, 1, MON_TMD_FLG_NOTIFY, sink);
1516
+ }
1517
+ }
1518
+ if ((mon.mTimed[MON_TMD.CHANGED] ?? 0) > 0) {
1519
+ monDecTimed(state.rng, mon, MON_TMD.CHANGED, 1, MON_TMD_FLG_NOTIFY, sink, shape);
1520
+ }
1521
+ if (mon.mTimed[MON_TMD.FEAR] ?? 0) {
1522
+ const d = state.rng.randint1(Math.trunc(mon.race.level / 10) + 1);
1523
+ monDecTimed(state.rng, mon, MON_TMD.FEAR, d, MON_TMD_FLG_NOTIFY, sink);
1524
+ }
1525
+ if ((mon.mTimed[MON_TMD.HOLD] ?? 0) || (mon.mTimed[MON_TMD.COMMAND] ?? 0)) {
1526
+ return true;
1527
+ }
1528
+ if (mon.mTimed[MON_TMD.STUN] ?? 0) {
1529
+ return state.rng.oneIn(STUN_MISS_CHANCE);
1530
+ }
1531
+ return false;
1532
+ }
1533
+ /** monster_check_active: set/clear MFLAG_ACTIVE, return whether active. */
1534
+ export function monsterCheckActive(mon, state) {
1535
+ let active = false;
1536
+ if (mon.cdis <= mon.race.hearing && monsterPassesWalls(mon)) {
1537
+ active = true;
1538
+ }
1539
+ else if (mon.hp < mon.maxhp) {
1540
+ active = true;
1541
+ }
1542
+ else if (squareIsView(state.chunk, mon.grid)) {
1543
+ active = true;
1544
+ }
1545
+ else if (monsterCanHear(mon, state)) {
1546
+ active = true;
1547
+ }
1548
+ else if (monsterCanSmell(mon, state)) {
1549
+ active = true;
1550
+ }
1551
+ else if (monsterTakingTerrainDamage(state, mon)) {
1552
+ active = true;
1553
+ }
1554
+ if (active)
1555
+ mon.mflag.on(MFLAG.ACTIVE);
1556
+ else
1557
+ mon.mflag.off(MFLAG.ACTIVE);
1558
+ return active;
1559
+ }
1560
+ //# sourceMappingURL=monster-turn.js.map