@rpgm-tools/neo-angband-core 0.17.0 → 0.19.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 (853) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/perceive.d.ts.map +1 -1
  3. package/dist/agent/perceive.js +2 -2
  4. package/dist/agent/perceive.js.map +1 -1
  5. package/dist/combat/blow-vectors.d.ts +78 -0
  6. package/dist/combat/blow-vectors.d.ts.map +1 -0
  7. package/dist/combat/blow-vectors.fixtures.d.ts +19 -0
  8. package/dist/combat/blow-vectors.fixtures.d.ts.map +1 -0
  9. package/dist/combat/blow-vectors.fixtures.js +81 -0
  10. package/dist/combat/blow-vectors.fixtures.js.map +1 -0
  11. package/dist/combat/blow-vectors.js +195 -0
  12. package/dist/combat/blow-vectors.js.map +1 -0
  13. package/dist/combat/brand-slay.d.ts +22 -9
  14. package/dist/combat/brand-slay.d.ts.map +1 -1
  15. package/dist/combat/brand-slay.js +37 -10
  16. package/dist/combat/brand-slay.js.map +1 -1
  17. package/dist/combat/index.d.ts +1 -1
  18. package/dist/combat/index.js +1 -1
  19. package/dist/combat/melee.d.ts +25 -13
  20. package/dist/combat/melee.d.ts.map +1 -1
  21. package/dist/combat/melee.js +23 -19
  22. package/dist/combat/melee.js.map +1 -1
  23. package/dist/combat/mon-melee.d.ts +166 -7
  24. package/dist/combat/mon-melee.d.ts.map +1 -1
  25. package/dist/combat/mon-melee.js +469 -338
  26. package/dist/combat/mon-melee.js.map +1 -1
  27. package/dist/combat/ranged.d.ts +15 -13
  28. package/dist/combat/ranged.d.ts.map +1 -1
  29. package/dist/combat/ranged.js +31 -29
  30. package/dist/combat/ranged.js.map +1 -1
  31. package/dist/constants.d.ts +14 -0
  32. package/dist/constants.d.ts.map +1 -1
  33. package/dist/constants.js +14 -0
  34. package/dist/constants.js.map +1 -1
  35. package/dist/datafile.d.ts +48 -0
  36. package/dist/datafile.d.ts.map +1 -0
  37. package/dist/datafile.js +102 -0
  38. package/dist/datafile.js.map +1 -0
  39. package/dist/effects/effect-info-registry.d.ts +237 -0
  40. package/dist/effects/effect-info-registry.d.ts.map +1 -0
  41. package/dist/effects/effect-info-registry.js +138 -0
  42. package/dist/effects/effect-info-registry.js.map +1 -0
  43. package/dist/effects/effect-info-vectors.d.ts +92 -0
  44. package/dist/effects/effect-info-vectors.d.ts.map +1 -0
  45. package/dist/effects/effect-info-vectors.fixtures.d.ts +18 -0
  46. package/dist/effects/effect-info-vectors.fixtures.d.ts.map +1 -0
  47. package/dist/effects/effect-info-vectors.fixtures.js +51 -0
  48. package/dist/effects/effect-info-vectors.fixtures.js.map +1 -0
  49. package/dist/effects/effect-info-vectors.js +315 -0
  50. package/dist/effects/effect-info-vectors.js.map +1 -0
  51. package/dist/effects/effect-info.d.ts +5 -1
  52. package/dist/effects/effect-info.d.ts.map +1 -1
  53. package/dist/effects/effect-info.js +245 -143
  54. package/dist/effects/effect-info.js.map +1 -1
  55. package/dist/effects/effect.d.ts +4 -3
  56. package/dist/effects/effect.d.ts.map +1 -1
  57. package/dist/effects/effect.js +88 -70
  58. package/dist/effects/effect.js.map +1 -1
  59. package/dist/effects/handlers.d.ts +1 -1
  60. package/dist/effects/handlers.d.ts.map +1 -1
  61. package/dist/effects/handlers.js +5 -2
  62. package/dist/effects/handlers.js.map +1 -1
  63. package/dist/effects/interpreter.d.ts +11 -0
  64. package/dist/effects/interpreter.d.ts.map +1 -1
  65. package/dist/effects/interpreter.js +13 -0
  66. package/dist/effects/interpreter.js.map +1 -1
  67. package/dist/game/cave-cmd.d.ts +9 -5
  68. package/dist/game/cave-cmd.d.ts.map +1 -1
  69. package/dist/game/cave-cmd.js +56 -11
  70. package/dist/game/cave-cmd.js.map +1 -1
  71. package/dist/game/cave-square.d.ts +42 -0
  72. package/dist/game/cave-square.d.ts.map +1 -0
  73. package/dist/game/cave-square.js +73 -0
  74. package/dist/game/cave-square.js.map +1 -0
  75. package/dist/game/char-sheet.d.ts +12 -8
  76. package/dist/game/char-sheet.d.ts.map +1 -1
  77. package/dist/game/char-sheet.js +41 -8
  78. package/dist/game/char-sheet.js.map +1 -1
  79. package/dist/game/chest.d.ts +2 -3
  80. package/dist/game/chest.d.ts.map +1 -1
  81. package/dist/game/chest.js +17 -6
  82. package/dist/game/chest.js.map +1 -1
  83. package/dist/game/context.d.ts +213 -22
  84. package/dist/game/context.d.ts.map +1 -1
  85. package/dist/game/context.js +109 -17
  86. package/dist/game/context.js.map +1 -1
  87. package/dist/game/describe.d.ts +13 -0
  88. package/dist/game/describe.d.ts.map +1 -1
  89. package/dist/game/describe.js +32 -4
  90. package/dist/game/describe.js.map +1 -1
  91. package/dist/game/display.d.ts +97 -8
  92. package/dist/game/display.d.ts.map +1 -1
  93. package/dist/game/display.js +157 -13
  94. package/dist/game/display.js.map +1 -1
  95. package/dist/game/dump-level.d.ts.map +1 -1
  96. package/dist/game/dump-level.js +3 -2
  97. package/dist/game/dump-level.js.map +1 -1
  98. package/dist/game/effect-attack.d.ts.map +1 -1
  99. package/dist/game/effect-attack.js +36 -27
  100. package/dist/game/effect-attack.js.map +1 -1
  101. package/dist/game/effect-detect.d.ts +4 -4
  102. package/dist/game/effect-detect.d.ts.map +1 -1
  103. package/dist/game/effect-detect.js +42 -9
  104. package/dist/game/effect-detect.js.map +1 -1
  105. package/dist/game/effect-env.d.ts +7 -1
  106. package/dist/game/effect-env.d.ts.map +1 -1
  107. package/dist/game/effect-env.js +1 -0
  108. package/dist/game/effect-env.js.map +1 -1
  109. package/dist/game/effect-general.d.ts +5 -3
  110. package/dist/game/effect-general.d.ts.map +1 -1
  111. package/dist/game/effect-general.js +94 -43
  112. package/dist/game/effect-general.js.map +1 -1
  113. package/dist/game/effect-item.d.ts +2 -1
  114. package/dist/game/effect-item.d.ts.map +1 -1
  115. package/dist/game/effect-item.js +136 -82
  116. package/dist/game/effect-item.js.map +1 -1
  117. package/dist/game/effect-melee.d.ts +10 -4
  118. package/dist/game/effect-melee.d.ts.map +1 -1
  119. package/dist/game/effect-melee.js +44 -19
  120. package/dist/game/effect-melee.js.map +1 -1
  121. package/dist/game/effect-monster.d.ts +26 -4
  122. package/dist/game/effect-monster.d.ts.map +1 -1
  123. package/dist/game/effect-monster.js +52 -9
  124. package/dist/game/effect-monster.js.map +1 -1
  125. package/dist/game/effect-teleport.d.ts +58 -19
  126. package/dist/game/effect-teleport.d.ts.map +1 -1
  127. package/dist/game/effect-teleport.js +143 -27
  128. package/dist/game/effect-teleport.js.map +1 -1
  129. package/dist/game/effect-terrain.d.ts +1 -3
  130. package/dist/game/effect-terrain.d.ts.map +1 -1
  131. package/dist/game/effect-terrain.js +38 -22
  132. package/dist/game/effect-terrain.js.map +1 -1
  133. package/dist/game/equip-cmp.d.ts.map +1 -1
  134. package/dist/game/equip-cmp.js +10 -7
  135. package/dist/game/equip-cmp.js.map +1 -1
  136. package/dist/game/floor.d.ts +16 -4
  137. package/dist/game/floor.d.ts.map +1 -1
  138. package/dist/game/floor.js +22 -4
  139. package/dist/game/floor.js.map +1 -1
  140. package/dist/game/gear.d.ts +101 -13
  141. package/dist/game/gear.d.ts.map +1 -1
  142. package/dist/game/gear.js +183 -24
  143. package/dist/game/gear.js.map +1 -1
  144. package/dist/game/harness.d.ts +2 -1
  145. package/dist/game/harness.d.ts.map +1 -1
  146. package/dist/game/harness.js +12 -1
  147. package/dist/game/harness.js.map +1 -1
  148. package/dist/game/ignore-cmd.d.ts +47 -8
  149. package/dist/game/ignore-cmd.d.ts.map +1 -1
  150. package/dist/game/ignore-cmd.js +76 -8
  151. package/dist/game/ignore-cmd.js.map +1 -1
  152. package/dist/game/known.d.ts +223 -34
  153. package/dist/game/known.d.ts.map +1 -1
  154. package/dist/game/known.js +301 -67
  155. package/dist/game/known.js.map +1 -1
  156. package/dist/game/loop.d.ts +4 -3
  157. package/dist/game/loop.d.ts.map +1 -1
  158. package/dist/game/loop.js +49 -29
  159. package/dist/game/loop.js.map +1 -1
  160. package/dist/game/lore-color.d.ts.map +1 -1
  161. package/dist/game/lore-color.js +13 -1
  162. package/dist/game/lore-color.js.map +1 -1
  163. package/dist/game/mon-cast.d.ts +3 -4
  164. package/dist/game/mon-cast.d.ts.map +1 -1
  165. package/dist/game/mon-cast.js +30 -2
  166. package/dist/game/mon-cast.js.map +1 -1
  167. package/dist/game/mon-cmd.d.ts +4 -5
  168. package/dist/game/mon-cmd.d.ts.map +1 -1
  169. package/dist/game/mon-cmd.js +80 -27
  170. package/dist/game/mon-cmd.js.map +1 -1
  171. package/dist/game/mon-death.d.ts +8 -4
  172. package/dist/game/mon-death.d.ts.map +1 -1
  173. package/dist/game/mon-death.js +6 -9
  174. package/dist/game/mon-death.js.map +1 -1
  175. package/dist/game/mon-group.d.ts +9 -5
  176. package/dist/game/mon-group.d.ts.map +1 -1
  177. package/dist/game/mon-group.js +9 -5
  178. package/dist/game/mon-group.js.map +1 -1
  179. package/dist/game/mon-message.d.ts +90 -40
  180. package/dist/game/mon-message.d.ts.map +1 -1
  181. package/dist/game/mon-message.js +267 -59
  182. package/dist/game/mon-message.js.map +1 -1
  183. package/dist/game/mon-place.d.ts +11 -1
  184. package/dist/game/mon-place.d.ts.map +1 -1
  185. package/dist/game/mon-place.js +15 -3
  186. package/dist/game/mon-place.js.map +1 -1
  187. package/dist/game/mon-ranged.d.ts +2 -1
  188. package/dist/game/mon-ranged.d.ts.map +1 -1
  189. package/dist/game/mon-ranged.js +11 -5
  190. package/dist/game/mon-ranged.js.map +1 -1
  191. package/dist/game/mon-side.d.ts +3 -2
  192. package/dist/game/mon-side.d.ts.map +1 -1
  193. package/dist/game/mon-side.js +15 -14
  194. package/dist/game/mon-side.js.map +1 -1
  195. package/dist/game/monster-turn.d.ts +20 -10
  196. package/dist/game/monster-turn.d.ts.map +1 -1
  197. package/dist/game/monster-turn.js +110 -83
  198. package/dist/game/monster-turn.js.map +1 -1
  199. package/dist/game/notice.d.ts +36 -0
  200. package/dist/game/notice.d.ts.map +1 -0
  201. package/dist/game/notice.js +79 -0
  202. package/dist/game/notice.js.map +1 -0
  203. package/dist/game/obj-cmd.d.ts +14 -3
  204. package/dist/game/obj-cmd.d.ts.map +1 -1
  205. package/dist/game/obj-cmd.js +109 -35
  206. package/dist/game/obj-cmd.js.map +1 -1
  207. package/dist/game/obj-list.d.ts +13 -2
  208. package/dist/game/obj-list.d.ts.map +1 -1
  209. package/dist/game/obj-list.js +42 -27
  210. package/dist/game/obj-list.js.map +1 -1
  211. package/dist/game/object-inspect.d.ts +9 -0
  212. package/dist/game/object-inspect.d.ts.map +1 -1
  213. package/dist/game/object-inspect.js +4 -0
  214. package/dist/game/object-inspect.js.map +1 -1
  215. package/dist/game/pickup.d.ts +0 -2
  216. package/dist/game/pickup.d.ts.map +1 -1
  217. package/dist/game/pickup.js +18 -3
  218. package/dist/game/pickup.js.map +1 -1
  219. package/dist/game/player-side-vectors.d.ts +174 -0
  220. package/dist/game/player-side-vectors.d.ts.map +1 -0
  221. package/dist/game/player-side-vectors.fixtures.d.ts +33 -0
  222. package/dist/game/player-side-vectors.fixtures.d.ts.map +1 -0
  223. package/dist/game/player-side-vectors.fixtures.js +191 -0
  224. package/dist/game/player-side-vectors.fixtures.js.map +1 -0
  225. package/dist/game/player-side-vectors.js +292 -0
  226. package/dist/game/player-side-vectors.js.map +1 -0
  227. package/dist/game/player-side.d.ts +129 -1
  228. package/dist/game/player-side.d.ts.map +1 -1
  229. package/dist/game/player-side.js +520 -338
  230. package/dist/game/player-side.js.map +1 -1
  231. package/dist/game/player-turn.d.ts +26 -7
  232. package/dist/game/player-turn.d.ts.map +1 -1
  233. package/dist/game/player-turn.js +180 -33
  234. package/dist/game/player-turn.js.map +1 -1
  235. package/dist/game/poly.d.ts +38 -0
  236. package/dist/game/poly.d.ts.map +1 -0
  237. package/dist/game/poly.js +82 -0
  238. package/dist/game/poly.js.map +1 -0
  239. package/dist/game/project-cast.d.ts +20 -3
  240. package/dist/game/project-cast.d.ts.map +1 -1
  241. package/dist/game/project-cast.js +49 -6
  242. package/dist/game/project-cast.js.map +1 -1
  243. package/dist/game/project-feat-vectors.d.ts +124 -0
  244. package/dist/game/project-feat-vectors.d.ts.map +1 -0
  245. package/dist/game/project-feat-vectors.fixtures.d.ts +13 -0
  246. package/dist/game/project-feat-vectors.fixtures.d.ts.map +1 -0
  247. package/dist/game/project-feat-vectors.fixtures.js +94 -0
  248. package/dist/game/project-feat-vectors.fixtures.js.map +1 -0
  249. package/dist/game/project-feat-vectors.js +229 -0
  250. package/dist/game/project-feat-vectors.js.map +1 -0
  251. package/dist/game/project-feat.d.ts +53 -1
  252. package/dist/game/project-feat.d.ts.map +1 -1
  253. package/dist/game/project-feat.js +374 -247
  254. package/dist/game/project-feat.js.map +1 -1
  255. package/dist/game/project-monster.d.ts +21 -8
  256. package/dist/game/project-monster.d.ts.map +1 -1
  257. package/dist/game/project-monster.js +45 -21
  258. package/dist/game/project-monster.js.map +1 -1
  259. package/dist/game/project-obj.d.ts +62 -0
  260. package/dist/game/project-obj.d.ts.map +1 -1
  261. package/dist/game/project-obj.js +72 -41
  262. package/dist/game/project-obj.js.map +1 -1
  263. package/dist/game/project-player.d.ts +8 -0
  264. package/dist/game/project-player.d.ts.map +1 -1
  265. package/dist/game/project-player.js.map +1 -1
  266. package/dist/game/projection-handlers.d.ts +81 -0
  267. package/dist/game/projection-handlers.d.ts.map +1 -0
  268. package/dist/game/projection-handlers.js +93 -0
  269. package/dist/game/projection-handlers.js.map +1 -0
  270. package/dist/game/quest.d.ts +23 -0
  271. package/dist/game/quest.d.ts.map +1 -1
  272. package/dist/game/quest.js +42 -0
  273. package/dist/game/quest.js.map +1 -1
  274. package/dist/game/ranged-cmd.d.ts +13 -2
  275. package/dist/game/ranged-cmd.d.ts.map +1 -1
  276. package/dist/game/ranged-cmd.js +32 -15
  277. package/dist/game/ranged-cmd.js.map +1 -1
  278. package/dist/game/repeat.d.ts +78 -0
  279. package/dist/game/repeat.d.ts.map +1 -0
  280. package/dist/game/repeat.js +88 -0
  281. package/dist/game/repeat.js.map +1 -0
  282. package/dist/game/shape-inspect.d.ts +74 -0
  283. package/dist/game/shape-inspect.d.ts.map +1 -0
  284. package/dist/game/shape-inspect.js +114 -0
  285. package/dist/game/shape-inspect.js.map +1 -0
  286. package/dist/game/spell-cmd.d.ts +15 -4
  287. package/dist/game/spell-cmd.d.ts.map +1 -1
  288. package/dist/game/spell-cmd.js +35 -6
  289. package/dist/game/spell-cmd.js.map +1 -1
  290. package/dist/game/spoil.d.ts.map +1 -1
  291. package/dist/game/spoil.js +89 -40
  292. package/dist/game/spoil.js.map +1 -1
  293. package/dist/game/steal.d.ts +3 -3
  294. package/dist/game/steal.d.ts.map +1 -1
  295. package/dist/game/steal.js +9 -4
  296. package/dist/game/steal.js.map +1 -1
  297. package/dist/game/target-loop.d.ts +10 -4
  298. package/dist/game/target-loop.d.ts.map +1 -1
  299. package/dist/game/target-loop.js +14 -8
  300. package/dist/game/target-loop.js.map +1 -1
  301. package/dist/game/target.d.ts +4 -4
  302. package/dist/game/target.d.ts.map +1 -1
  303. package/dist/game/target.js +19 -8
  304. package/dist/game/target.js.map +1 -1
  305. package/dist/game/ui-entry.d.ts +63 -4
  306. package/dist/game/ui-entry.d.ts.map +1 -1
  307. package/dist/game/ui-entry.js +151 -23
  308. package/dist/game/ui-entry.js.map +1 -1
  309. package/dist/game/wizard.d.ts +23 -5
  310. package/dist/game/wizard.d.ts.map +1 -1
  311. package/dist/game/wizard.js +93 -11
  312. package/dist/game/wizard.js.map +1 -1
  313. package/dist/game/world.d.ts.map +1 -1
  314. package/dist/game/world.js +6 -0
  315. package/dist/game/world.js.map +1 -1
  316. package/dist/gen/cave.d.ts +49 -8
  317. package/dist/gen/cave.d.ts.map +1 -1
  318. package/dist/gen/cave.js +200 -28
  319. package/dist/gen/cave.js.map +1 -1
  320. package/dist/gen/generate.d.ts +54 -9
  321. package/dist/gen/generate.d.ts.map +1 -1
  322. package/dist/gen/generate.js +55 -8
  323. package/dist/gen/generate.js.map +1 -1
  324. package/dist/gen/glyph-vectors.d.ts +109 -0
  325. package/dist/gen/glyph-vectors.d.ts.map +1 -0
  326. package/dist/gen/glyph-vectors.fixtures.d.ts +18 -0
  327. package/dist/gen/glyph-vectors.fixtures.d.ts.map +1 -0
  328. package/dist/gen/glyph-vectors.fixtures.js +94 -0
  329. package/dist/gen/glyph-vectors.fixtures.js.map +1 -0
  330. package/dist/gen/glyph-vectors.js +218 -0
  331. package/dist/gen/glyph-vectors.js.map +1 -0
  332. package/dist/gen/glyph.d.ts +104 -0
  333. package/dist/gen/glyph.d.ts.map +1 -0
  334. package/dist/gen/glyph.js +72 -0
  335. package/dist/gen/glyph.js.map +1 -0
  336. package/dist/gen/room.d.ts +26 -2
  337. package/dist/gen/room.d.ts.map +1 -1
  338. package/dist/gen/room.js +414 -264
  339. package/dist/gen/room.js.map +1 -1
  340. package/dist/gen/util.d.ts +11 -2
  341. package/dist/gen/util.d.ts.map +1 -1
  342. package/dist/gen/util.js +31 -9
  343. package/dist/gen/util.js.map +1 -1
  344. package/dist/i18n/i18n.d.ts +207 -0
  345. package/dist/i18n/i18n.d.ts.map +1 -0
  346. package/dist/i18n/i18n.js +405 -0
  347. package/dist/i18n/i18n.js.map +1 -0
  348. package/dist/i18n/text.d.ts +62 -0
  349. package/dist/i18n/text.d.ts.map +1 -0
  350. package/dist/i18n/text.js +120 -0
  351. package/dist/i18n/text.js.map +1 -0
  352. package/dist/index.d.ts +25 -0
  353. package/dist/index.d.ts.map +1 -1
  354. package/dist/index.js +38 -0
  355. package/dist/index.js.map +1 -1
  356. package/dist/mod/extension.d.ts +115 -0
  357. package/dist/mod/extension.d.ts.map +1 -0
  358. package/dist/mod/extension.js +85 -0
  359. package/dist/mod/extension.js.map +1 -0
  360. package/dist/mod/hooks.d.ts +27 -1
  361. package/dist/mod/hooks.d.ts.map +1 -1
  362. package/dist/mod/hooks.js +23 -0
  363. package/dist/mod/hooks.js.map +1 -1
  364. package/dist/mod/ids.d.ts +10 -0
  365. package/dist/mod/ids.d.ts.map +1 -1
  366. package/dist/mod/ids.js +90 -21
  367. package/dist/mod/ids.js.map +1 -1
  368. package/dist/mod/record-keys.d.ts +43 -0
  369. package/dist/mod/record-keys.d.ts.map +1 -0
  370. package/dist/mod/record-keys.js +100 -0
  371. package/dist/mod/record-keys.js.map +1 -0
  372. package/dist/mod/registry-host.d.ts +472 -0
  373. package/dist/mod/registry-host.d.ts.map +1 -1
  374. package/dist/mod/registry-host.js +313 -0
  375. package/dist/mod/registry-host.js.map +1 -1
  376. package/dist/mod/save-blocks.d.ts +1 -1
  377. package/dist/mon/bind.d.ts.map +1 -1
  378. package/dist/mon/bind.js +6 -3
  379. package/dist/mon/bind.js.map +1 -1
  380. package/dist/mon/knowledge-groups.d.ts +0 -6
  381. package/dist/mon/knowledge-groups.d.ts.map +1 -1
  382. package/dist/mon/knowledge-groups.js +12 -8
  383. package/dist/mon/knowledge-groups.js.map +1 -1
  384. package/dist/mon/lore-describe.d.ts +46 -10
  385. package/dist/mon/lore-describe.d.ts.map +1 -1
  386. package/dist/mon/lore-describe.js +74 -22
  387. package/dist/mon/lore-describe.js.map +1 -1
  388. package/dist/mon/lore-file.d.ts +126 -0
  389. package/dist/mon/lore-file.d.ts.map +1 -0
  390. package/dist/mon/lore-file.js +291 -0
  391. package/dist/mon/lore-file.js.map +1 -0
  392. package/dist/mon/lore.d.ts +9 -3
  393. package/dist/mon/lore.d.ts.map +1 -1
  394. package/dist/mon/lore.js +9 -3
  395. package/dist/mon/lore.js.map +1 -1
  396. package/dist/mon/make.d.ts +4 -2
  397. package/dist/mon/make.d.ts.map +1 -1
  398. package/dist/mon/make.js +4 -2
  399. package/dist/mon/make.js.map +1 -1
  400. package/dist/mon/monster.d.ts +1 -1
  401. package/dist/mon/monster.js +1 -1
  402. package/dist/mon/predicate.d.ts +14 -9
  403. package/dist/mon/predicate.d.ts.map +1 -1
  404. package/dist/mon/predicate.js +14 -9
  405. package/dist/mon/predicate.js.map +1 -1
  406. package/dist/mon/project-mon.d.ts +16 -3
  407. package/dist/mon/project-mon.d.ts.map +1 -1
  408. package/dist/mon/project-mon.js +14 -5
  409. package/dist/mon/project-mon.js.map +1 -1
  410. package/dist/mon/steal.d.ts +31 -4
  411. package/dist/mon/steal.d.ts.map +1 -1
  412. package/dist/mon/steal.js +20 -7
  413. package/dist/mon/steal.js.map +1 -1
  414. package/dist/mon/take-hit.d.ts +8 -3
  415. package/dist/mon/take-hit.d.ts.map +1 -1
  416. package/dist/mon/take-hit.js +8 -3
  417. package/dist/mon/take-hit.js.map +1 -1
  418. package/dist/mon/timed.d.ts +15 -9
  419. package/dist/mon/timed.d.ts.map +1 -1
  420. package/dist/mon/timed.js +13 -8
  421. package/dist/mon/timed.js.map +1 -1
  422. package/dist/mon/types.d.ts +11 -4
  423. package/dist/mon/types.d.ts.map +1 -1
  424. package/dist/mon/types.js.map +1 -1
  425. package/dist/msg.d.ts +40 -1
  426. package/dist/msg.d.ts.map +1 -1
  427. package/dist/msg.js +42 -1
  428. package/dist/msg.js.map +1 -1
  429. package/dist/obj/artifact-fake.d.ts +46 -14
  430. package/dist/obj/artifact-fake.d.ts.map +1 -1
  431. package/dist/obj/artifact-fake.js +46 -17
  432. package/dist/obj/artifact-fake.js.map +1 -1
  433. package/dist/obj/bind.d.ts +23 -0
  434. package/dist/obj/bind.d.ts.map +1 -1
  435. package/dist/obj/bind.js +49 -9
  436. package/dist/obj/bind.js.map +1 -1
  437. package/dist/obj/desc-vectors.d.ts +68 -0
  438. package/dist/obj/desc-vectors.d.ts.map +1 -0
  439. package/dist/obj/desc-vectors.fixtures.d.ts +12 -0
  440. package/dist/obj/desc-vectors.fixtures.d.ts.map +1 -0
  441. package/dist/obj/desc-vectors.fixtures.js +95 -0
  442. package/dist/obj/desc-vectors.fixtures.js.map +1 -0
  443. package/dist/obj/desc-vectors.js +86 -0
  444. package/dist/obj/desc-vectors.js.map +1 -0
  445. package/dist/obj/desc.d.ts +17 -2
  446. package/dist/obj/desc.d.ts.map +1 -1
  447. package/dist/obj/desc.js +129 -54
  448. package/dist/obj/desc.js.map +1 -1
  449. package/dist/obj/effects-info.d.ts.map +1 -1
  450. package/dist/obj/effects-info.js +87 -58
  451. package/dist/obj/effects-info.js.map +1 -1
  452. package/dist/obj/fake-object.d.ts +70 -0
  453. package/dist/obj/fake-object.d.ts.map +1 -0
  454. package/dist/obj/fake-object.js +104 -0
  455. package/dist/obj/fake-object.js.map +1 -0
  456. package/dist/obj/ignore.d.ts +55 -12
  457. package/dist/obj/ignore.d.ts.map +1 -1
  458. package/dist/obj/ignore.js +68 -31
  459. package/dist/obj/ignore.js.map +1 -1
  460. package/dist/obj/knowledge.d.ts +46 -3
  461. package/dist/obj/knowledge.d.ts.map +1 -1
  462. package/dist/obj/knowledge.js +169 -151
  463. package/dist/obj/knowledge.js.map +1 -1
  464. package/dist/obj/known-object.d.ts +68 -8
  465. package/dist/obj/known-object.d.ts.map +1 -1
  466. package/dist/obj/known-object.js +90 -10
  467. package/dist/obj/known-object.js.map +1 -1
  468. package/dist/obj/make.d.ts +15 -4
  469. package/dist/obj/make.d.ts.map +1 -1
  470. package/dist/obj/make.js +49 -27
  471. package/dist/obj/make.js.map +1 -1
  472. package/dist/obj/object-info.d.ts +10 -0
  473. package/dist/obj/object-info.d.ts.map +1 -1
  474. package/dist/obj/object-info.js +93 -7
  475. package/dist/obj/object-info.js.map +1 -1
  476. package/dist/obj/object.d.ts +42 -4
  477. package/dist/obj/object.d.ts.map +1 -1
  478. package/dist/obj/object.js +362 -147
  479. package/dist/obj/object.js.map +1 -1
  480. package/dist/obj/power.d.ts +23 -4
  481. package/dist/obj/power.d.ts.map +1 -1
  482. package/dist/obj/power.js +231 -65
  483. package/dist/obj/power.js.map +1 -1
  484. package/dist/obj/randart-build.d.ts +27 -22
  485. package/dist/obj/randart-build.d.ts.map +1 -1
  486. package/dist/obj/randart-build.js +435 -357
  487. package/dist/obj/randart-build.js.map +1 -1
  488. package/dist/obj/randart-data.d.ts +62 -24
  489. package/dist/obj/randart-data.d.ts.map +1 -1
  490. package/dist/obj/randart-data.js +333 -189
  491. package/dist/obj/randart-data.js.map +1 -1
  492. package/dist/obj/randart-file.d.ts +21 -0
  493. package/dist/obj/randart-file.d.ts.map +1 -0
  494. package/dist/obj/randart-file.js +119 -0
  495. package/dist/obj/randart-file.js.map +1 -0
  496. package/dist/obj/randart-log.d.ts +63 -0
  497. package/dist/obj/randart-log.d.ts.map +1 -0
  498. package/dist/obj/randart-log.js +72 -0
  499. package/dist/obj/randart-log.js.map +1 -0
  500. package/dist/obj/randart-registry.d.ts +178 -0
  501. package/dist/obj/randart-registry.d.ts.map +1 -0
  502. package/dist/obj/randart-registry.js +140 -0
  503. package/dist/obj/randart-registry.js.map +1 -0
  504. package/dist/obj/randart-vectors.d.ts +97 -0
  505. package/dist/obj/randart-vectors.d.ts.map +1 -0
  506. package/dist/obj/randart-vectors.fixtures.d.ts +18 -0
  507. package/dist/obj/randart-vectors.fixtures.d.ts.map +1 -0
  508. package/dist/obj/randart-vectors.fixtures.js +50 -0
  509. package/dist/obj/randart-vectors.fixtures.js.map +1 -0
  510. package/dist/obj/randart-vectors.js +311 -0
  511. package/dist/obj/randart-vectors.js.map +1 -0
  512. package/dist/obj/randart.d.ts +53 -15
  513. package/dist/obj/randart.d.ts.map +1 -1
  514. package/dist/obj/randart.js +166 -44
  515. package/dist/obj/randart.js.map +1 -1
  516. package/dist/obj/rune-registry.d.ts +180 -0
  517. package/dist/obj/rune-registry.d.ts.map +1 -0
  518. package/dist/obj/rune-registry.js +161 -0
  519. package/dist/obj/rune-registry.js.map +1 -0
  520. package/dist/obj/rune-vectors.d.ts +99 -0
  521. package/dist/obj/rune-vectors.d.ts.map +1 -0
  522. package/dist/obj/rune-vectors.fixtures.d.ts +44 -0
  523. package/dist/obj/rune-vectors.fixtures.d.ts.map +1 -0
  524. package/dist/obj/rune-vectors.fixtures.js +125 -0
  525. package/dist/obj/rune-vectors.fixtures.js.map +1 -0
  526. package/dist/obj/rune-vectors.js +159 -0
  527. package/dist/obj/rune-vectors.js.map +1 -0
  528. package/dist/obj/tval-registry.d.ts +174 -0
  529. package/dist/obj/tval-registry.d.ts.map +1 -0
  530. package/dist/obj/tval-registry.js +151 -0
  531. package/dist/obj/tval-registry.js.map +1 -0
  532. package/dist/obj/tval-vectors.d.ts +85 -0
  533. package/dist/obj/tval-vectors.d.ts.map +1 -0
  534. package/dist/obj/tval-vectors.fixtures.d.ts +24 -0
  535. package/dist/obj/tval-vectors.fixtures.d.ts.map +1 -0
  536. package/dist/obj/tval-vectors.fixtures.js +41 -0
  537. package/dist/obj/tval-vectors.fixtures.js.map +1 -0
  538. package/dist/obj/tval-vectors.js +76 -0
  539. package/dist/obj/tval-vectors.js.map +1 -0
  540. package/dist/obj/types.d.ts +18 -7
  541. package/dist/obj/types.d.ts.map +1 -1
  542. package/dist/obj/types.js.map +1 -1
  543. package/dist/obj/value.d.ts.map +1 -1
  544. package/dist/obj/value.js +23 -20
  545. package/dist/obj/value.js.map +1 -1
  546. package/dist/parser.d.ts +116 -0
  547. package/dist/parser.d.ts.map +1 -0
  548. package/dist/parser.js +205 -0
  549. package/dist/parser.js.map +1 -0
  550. package/dist/player/bind.d.ts.map +1 -1
  551. package/dist/player/bind.js +3 -2
  552. package/dist/player/bind.js.map +1 -1
  553. package/dist/player/birth.d.ts +2 -1
  554. package/dist/player/birth.d.ts.map +1 -1
  555. package/dist/player/birth.js +2 -1
  556. package/dist/player/birth.js.map +1 -1
  557. package/dist/player/calcs.d.ts +58 -23
  558. package/dist/player/calcs.d.ts.map +1 -1
  559. package/dist/player/calcs.js +93 -36
  560. package/dist/player/calcs.js.map +1 -1
  561. package/dist/player/death.d.ts +50 -0
  562. package/dist/player/death.d.ts.map +1 -0
  563. package/dist/player/death.js +46 -0
  564. package/dist/player/death.js.map +1 -0
  565. package/dist/player/options-file.d.ts +129 -0
  566. package/dist/player/options-file.d.ts.map +1 -0
  567. package/dist/player/options-file.js +309 -0
  568. package/dist/player/options-file.js.map +1 -0
  569. package/dist/player/options.d.ts +2 -1
  570. package/dist/player/options.d.ts.map +1 -1
  571. package/dist/player/options.js +2 -1
  572. package/dist/player/options.js.map +1 -1
  573. package/dist/player/player.d.ts +50 -3
  574. package/dist/player/player.d.ts.map +1 -1
  575. package/dist/player/player.js +10 -1
  576. package/dist/player/player.js.map +1 -1
  577. package/dist/player/shape-lore.d.ts +11 -7
  578. package/dist/player/shape-lore.d.ts.map +1 -1
  579. package/dist/player/shape-lore.js +24 -11
  580. package/dist/player/shape-lore.js.map +1 -1
  581. package/dist/player/timed.d.ts +5 -3
  582. package/dist/player/timed.d.ts.map +1 -1
  583. package/dist/player/timed.js +11 -2
  584. package/dist/player/timed.js.map +1 -1
  585. package/dist/player/types.d.ts +29 -4
  586. package/dist/player/types.d.ts.map +1 -1
  587. package/dist/player/types.js +24 -1
  588. package/dist/player/types.js.map +1 -1
  589. package/dist/session/boot.d.ts +26 -2
  590. package/dist/session/boot.d.ts.map +1 -1
  591. package/dist/session/boot.js +21 -2
  592. package/dist/session/boot.js.map +1 -1
  593. package/dist/session/game.d.ts +15 -0
  594. package/dist/session/game.d.ts.map +1 -1
  595. package/dist/session/game.js +616 -140
  596. package/dist/session/game.js.map +1 -1
  597. package/dist/session/save-migrate.d.ts.map +1 -1
  598. package/dist/session/save-migrate.js +76 -1
  599. package/dist/session/save-migrate.js.map +1 -1
  600. package/dist/session/save.d.ts +75 -12
  601. package/dist/session/save.d.ts.map +1 -1
  602. package/dist/session/save.js +177 -18
  603. package/dist/session/save.js.map +1 -1
  604. package/dist/store/bind.d.ts +1 -1
  605. package/dist/store/bind.d.ts.map +1 -1
  606. package/dist/store/bind.js +4 -3
  607. package/dist/store/bind.js.map +1 -1
  608. package/dist/store/mass-produce-vectors.d.ts +40 -0
  609. package/dist/store/mass-produce-vectors.d.ts.map +1 -0
  610. package/dist/store/mass-produce-vectors.fixtures.d.ts +13 -0
  611. package/dist/store/mass-produce-vectors.fixtures.d.ts.map +1 -0
  612. package/dist/store/mass-produce-vectors.fixtures.js +52 -0
  613. package/dist/store/mass-produce-vectors.fixtures.js.map +1 -0
  614. package/dist/store/mass-produce-vectors.js +44 -0
  615. package/dist/store/mass-produce-vectors.js.map +1 -0
  616. package/dist/store/store.d.ts +104 -7
  617. package/dist/store/store.d.ts.map +1 -1
  618. package/dist/store/store.js +199 -77
  619. package/dist/store/store.js.map +1 -1
  620. package/dist/store/transact.d.ts +14 -5
  621. package/dist/store/transact.d.ts.map +1 -1
  622. package/dist/store/transact.js +17 -16
  623. package/dist/store/transact.js.map +1 -1
  624. package/dist/store/types.d.ts +3 -2
  625. package/dist/store/types.d.ts.map +1 -1
  626. package/dist/store/types.js +1 -1
  627. package/dist/version.d.ts +1 -1
  628. package/dist/version.js +1 -1
  629. package/dist/visuals/index.d.ts +1 -0
  630. package/dist/visuals/index.d.ts.map +1 -1
  631. package/dist/visuals/index.js +1 -0
  632. package/dist/visuals/index.js.map +1 -1
  633. package/dist/visuals/map-text.d.ts +8 -0
  634. package/dist/visuals/map-text.d.ts.map +1 -1
  635. package/dist/visuals/map-text.js +1 -1
  636. package/dist/visuals/map-text.js.map +1 -1
  637. package/dist/visuals/object-glyph.d.ts +56 -0
  638. package/dist/visuals/object-glyph.d.ts.map +1 -0
  639. package/dist/visuals/object-glyph.js +52 -0
  640. package/dist/visuals/object-glyph.js.map +1 -0
  641. package/dist/visuals/prefs.d.ts +14 -22
  642. package/dist/visuals/prefs.d.ts.map +1 -1
  643. package/dist/visuals/prefs.js +4 -23
  644. package/dist/visuals/prefs.js.map +1 -1
  645. package/dist/visuals/tile-prefs.d.ts +26 -0
  646. package/dist/visuals/tile-prefs.d.ts.map +1 -1
  647. package/dist/visuals/tile-prefs.js +28 -0
  648. package/dist/visuals/tile-prefs.js.map +1 -1
  649. package/dist/world/feature.d.ts +2 -1
  650. package/dist/world/feature.d.ts.map +1 -1
  651. package/dist/world/feature.js +2 -0
  652. package/dist/world/feature.js.map +1 -1
  653. package/dist/world/project.d.ts +10 -2
  654. package/dist/world/project.d.ts.map +1 -1
  655. package/dist/world/project.js +18 -6
  656. package/dist/world/project.js.map +1 -1
  657. package/dist/world/projection.d.ts +37 -3
  658. package/dist/world/projection.d.ts.map +1 -1
  659. package/dist/world/projection.js +69 -7
  660. package/dist/world/projection.js.map +1 -1
  661. package/dist/world/trap.d.ts +2 -1
  662. package/dist/world/trap.d.ts.map +1 -1
  663. package/dist/world/trap.js +2 -1
  664. package/dist/world/trap.js.map +1 -1
  665. package/dist/world/view.d.ts +1 -1
  666. package/dist/world/view.d.ts.map +1 -1
  667. package/dist/world/view.js +11 -3
  668. package/dist/world/view.js.map +1 -1
  669. package/package.json +1 -1
  670. package/src/agent/perceive.ts +2 -3
  671. package/src/combat/blow-vectors.fixtures.ts +99 -0
  672. package/src/combat/blow-vectors.json +482 -0
  673. package/src/combat/blow-vectors.ts +280 -0
  674. package/src/combat/brand-slay.ts +42 -11
  675. package/src/combat/index.ts +1 -1
  676. package/src/combat/melee.ts +37 -19
  677. package/src/combat/mon-melee.ts +611 -364
  678. package/src/combat/ranged.ts +43 -26
  679. package/src/constants.ts +15 -0
  680. package/src/datafile.ts +148 -0
  681. package/src/effects/effect-info-registry.ts +313 -0
  682. package/src/effects/effect-info-vectors.fixtures.ts +61 -0
  683. package/src/effects/effect-info-vectors.json +11532 -0
  684. package/src/effects/effect-info-vectors.ts +376 -0
  685. package/src/effects/effect-info.ts +1005 -859
  686. package/src/effects/effect.ts +96 -62
  687. package/src/effects/handlers.ts +5 -2
  688. package/src/effects/interpreter.ts +14 -0
  689. package/src/game/cave-cmd.ts +54 -11
  690. package/src/game/cave-square.ts +80 -0
  691. package/src/game/char-sheet.ts +59 -16
  692. package/src/game/chest.ts +25 -8
  693. package/src/game/context.ts +293 -27
  694. package/src/game/describe.ts +34 -4
  695. package/src/game/display.ts +215 -19
  696. package/src/game/dump-level.ts +3 -2
  697. package/src/game/effect-attack.ts +41 -28
  698. package/src/game/effect-detect.ts +45 -8
  699. package/src/game/effect-env.ts +8 -0
  700. package/src/game/effect-general.ts +110 -47
  701. package/src/game/effect-item.ts +1075 -999
  702. package/src/game/effect-melee.ts +51 -18
  703. package/src/game/effect-monster.ts +55 -9
  704. package/src/game/effect-teleport.ts +173 -38
  705. package/src/game/effect-terrain.ts +38 -22
  706. package/src/game/equip-cmp.ts +483 -480
  707. package/src/game/floor.ts +22 -4
  708. package/src/game/gear.ts +210 -21
  709. package/src/game/harness.ts +12 -1
  710. package/src/game/ignore-cmd.ts +96 -8
  711. package/src/game/known.ts +392 -73
  712. package/src/game/loop.ts +52 -27
  713. package/src/game/lore-color.ts +13 -1
  714. package/src/game/mon-cast.ts +31 -6
  715. package/src/game/mon-cmd.ts +95 -30
  716. package/src/game/mon-death.ts +14 -12
  717. package/src/game/mon-group.ts +9 -5
  718. package/src/game/mon-message.ts +363 -65
  719. package/src/game/mon-place.ts +15 -3
  720. package/src/game/mon-ranged.ts +14 -5
  721. package/src/game/mon-side.ts +16 -12
  722. package/src/game/monster-turn.ts +120 -87
  723. package/src/game/notice.ts +85 -0
  724. package/src/game/obj-cmd.ts +126 -37
  725. package/src/game/obj-list.ts +44 -26
  726. package/src/game/object-inspect.ts +13 -0
  727. package/src/game/pickup.ts +29 -5
  728. package/src/game/player-side-vectors.fixtures.ts +215 -0
  729. package/src/game/player-side-vectors.json +6914 -0
  730. package/src/game/player-side-vectors.ts +420 -0
  731. package/src/game/player-side.ts +622 -340
  732. package/src/game/player-turn.ts +228 -31
  733. package/src/game/poly.ts +107 -0
  734. package/src/game/project-cast.ts +63 -6
  735. package/src/game/project-feat-vectors.fixtures.ts +106 -0
  736. package/src/game/project-feat-vectors.json +6554 -0
  737. package/src/game/project-feat-vectors.ts +323 -0
  738. package/src/game/project-feat.ts +417 -248
  739. package/src/game/project-monster.ts +69 -30
  740. package/src/game/project-obj-vectors.json +1 -0
  741. package/src/game/project-obj.ts +115 -47
  742. package/src/game/project-player.ts +8 -0
  743. package/src/game/projection-handlers.ts +110 -0
  744. package/src/game/quest.ts +48 -0
  745. package/src/game/ranged-cmd.ts +45 -11
  746. package/src/game/repeat.ts +92 -0
  747. package/src/game/shape-inspect.ts +166 -0
  748. package/src/game/spell-cmd.ts +39 -6
  749. package/src/game/spoil.ts +92 -39
  750. package/src/game/steal.ts +9 -4
  751. package/src/game/target-loop.ts +14 -7
  752. package/src/game/target.ts +18 -7
  753. package/src/game/ui-entry.ts +172 -22
  754. package/src/game/wizard.ts +97 -10
  755. package/src/game/world.ts +6 -0
  756. package/src/gen/cave.ts +225 -26
  757. package/src/gen/generate.ts +62 -9
  758. package/src/gen/glyph-vectors.fixtures.ts +122 -0
  759. package/src/gen/glyph-vectors.json +5996 -0
  760. package/src/gen/glyph-vectors.ts +280 -0
  761. package/src/gen/glyph.ts +132 -0
  762. package/src/gen/room.ts +446 -265
  763. package/src/gen/util.ts +32 -9
  764. package/src/i18n/i18n.ts +492 -0
  765. package/src/i18n/text.ts +117 -0
  766. package/src/index.ts +307 -254
  767. package/src/mod/extension.ts +136 -0
  768. package/src/mod/hooks.ts +54 -1
  769. package/src/mod/ids.ts +92 -21
  770. package/src/mod/record-keys.ts +102 -0
  771. package/src/mod/registry-host.ts +1063 -234
  772. package/src/mon/bind.ts +14 -8
  773. package/src/mon/knowledge-groups.ts +12 -12
  774. package/src/mon/lore-describe.ts +93 -26
  775. package/src/mon/lore-file.ts +365 -0
  776. package/src/mon/lore.ts +9 -3
  777. package/src/mon/make.ts +4 -2
  778. package/src/mon/monster.ts +1 -1
  779. package/src/mon/predicate.ts +14 -9
  780. package/src/mon/project-mon.ts +23 -5
  781. package/src/mon/steal.ts +39 -7
  782. package/src/mon/take-hit.ts +8 -3
  783. package/src/mon/timed.ts +15 -9
  784. package/src/mon/types.ts +11 -4
  785. package/src/msg.ts +55 -1
  786. package/src/obj/artifact-fake.ts +47 -17
  787. package/src/obj/bind.ts +52 -9
  788. package/src/obj/desc-vectors.fixtures.ts +119 -0
  789. package/src/obj/desc-vectors.json +2360 -0
  790. package/src/obj/desc-vectors.ts +128 -0
  791. package/src/obj/desc.ts +159 -55
  792. package/src/obj/effects-info.ts +90 -59
  793. package/src/obj/fake-object.ts +135 -0
  794. package/src/obj/ignore.ts +95 -28
  795. package/src/obj/knowledge.ts +291 -139
  796. package/src/obj/known-object.ts +126 -11
  797. package/src/obj/make.ts +53 -29
  798. package/src/obj/object-info.ts +103 -6
  799. package/src/obj/object.ts +392 -151
  800. package/src/obj/power.ts +297 -59
  801. package/src/obj/randart-build.ts +1875 -1705
  802. package/src/obj/randart-data.ts +1547 -1344
  803. package/src/obj/randart-file.ts +130 -0
  804. package/src/obj/randart-log.ts +78 -0
  805. package/src/obj/randart-registry.ts +247 -0
  806. package/src/obj/randart-vectors.fixtures.ts +61 -0
  807. package/src/obj/randart-vectors.json +836 -0
  808. package/src/obj/randart-vectors.ts +369 -0
  809. package/src/obj/randart.ts +722 -552
  810. package/src/obj/rune-registry.ts +270 -0
  811. package/src/obj/rune-vectors.fixtures.ts +164 -0
  812. package/src/obj/rune-vectors.json +121 -0
  813. package/src/obj/rune-vectors.ts +229 -0
  814. package/src/obj/tval-kind-vectors.json +391 -0
  815. package/src/obj/tval-registry.ts +243 -0
  816. package/src/obj/tval-vectors.fixtures.ts +50 -0
  817. package/src/obj/tval-vectors.json +38 -0
  818. package/src/obj/tval-vectors.ts +126 -0
  819. package/src/obj/types.ts +18 -7
  820. package/src/obj/value.ts +26 -20
  821. package/src/parser.ts +214 -0
  822. package/src/player/bind.ts +5 -2
  823. package/src/player/birth.ts +2 -1
  824. package/src/player/calcs.ts +123 -42
  825. package/src/player/death.ts +78 -0
  826. package/src/player/options-file.ts +387 -0
  827. package/src/player/options.ts +2 -1
  828. package/src/player/player.ts +60 -4
  829. package/src/player/shape-lore.ts +33 -14
  830. package/src/player/timed.ts +14 -4
  831. package/src/player/types.ts +30 -4
  832. package/src/session/boot.ts +51 -1
  833. package/src/session/game.ts +720 -163
  834. package/src/session/save-migrate.ts +81 -1
  835. package/src/session/save.ts +264 -22
  836. package/src/store/bind.ts +4 -3
  837. package/src/store/mass-produce-vectors.fixtures.ts +64 -0
  838. package/src/store/mass-produce-vectors.json +1169 -0
  839. package/src/store/mass-produce-vectors.ts +67 -0
  840. package/src/store/store.ts +266 -63
  841. package/src/store/transact.ts +39 -16
  842. package/src/store/types.ts +3 -2
  843. package/src/version.ts +1 -1
  844. package/src/visuals/index.ts +1 -0
  845. package/src/visuals/map-text.ts +1 -1
  846. package/src/visuals/object-glyph.ts +76 -0
  847. package/src/visuals/prefs.ts +22 -32
  848. package/src/visuals/tile-prefs.ts +32 -0
  849. package/src/world/feature.ts +4 -1
  850. package/src/world/project.ts +19 -4
  851. package/src/world/projection.ts +79 -8
  852. package/src/world/trap.ts +25 -21
  853. package/src/world/view.ts +11 -1
@@ -26,12 +26,16 @@
26
26
  * the PARALYZE damage=1 pre-clamp, and the "player moved" early-out (a blow that
27
27
  * relocates the player via earthquake / knockback skips the remaining blows).
28
28
  *
29
- * DEFERRED (ledgered in parity/ledger/combat-melee.yaml): monster lore /
30
- * smart-learn, monster-vs-monster melee (monster_attack_monster), react_to_slay
31
- * blocking a theft (the item is stolen regardless; no RNG impact), and attaching
32
- * stolen gold/items to the monster's held-object pile (monster_carry, coordinated
33
- * with the loot-drops gap; the item/gold is still removed from the player and no
34
- * RNG is drawn by the attach).
29
+ * All four items this header used to list as DEFERRED are ported: monster lore
30
+ * and smart-learn (mon/lore.ts loreLearnFlagIfVisible, project-player.ts:171),
31
+ * monster-vs-monster melee (game/mon-cmd.ts:317 monsterAttackMonster),
32
+ * react_to_slay blocking a theft on the player's pack (game/mon-side.ts:421) and
33
+ * attaching stolen gold/items to the thief's pile (mon/make.ts monsterCarry, used
34
+ * at game/known.ts:854).
35
+ *
36
+ * ONE REMAINS: the monster-vs-monster theft path does not apply react_to_slay
37
+ * (mon/steal.ts:234 vs mon-util.c:1548), so a slay-bearing item cannot resist
38
+ * being stolen by a monster from another monster. No RNG impact.
35
39
  */
36
40
  import { locEq } from "../loc.js";
37
41
  import { ELEM, MON_TMD, PROJ, RF, STAT, TMD } from "../generated/index.js";
@@ -233,153 +237,74 @@ function emitBlowMessageLive(env, ctx, reduced) {
233
237
  function drawBlowMessage(ctx) {
234
238
  displayBlowMessageVsPlayer(ctx.rng, ctx.method, 0, "", false, null);
235
239
  }
240
+ /**
241
+ * `melee_handler_for_blow_effect` (mon-blows.c:1191) as a real table.
242
+ *
243
+ * Core seeds this with its 30 handlers at boot (`registerCoreBlowEffects`), so a
244
+ * mod can ADD a 31st effect and have `blow_effects.json`'s new record actually
245
+ * do something, OVERRIDE one of the 30, or WRAP one - `handlerFor` returns the
246
+ * handler currently installed, which is what a wrapper needs to call through to.
247
+ *
248
+ * Same shape as `EffectRegistry` deliberately: a mod author who has learned one
249
+ * registry in this engine has learned them all.
250
+ */
251
+ export class BlowEffectRegistry {
252
+ handlers = new Map();
253
+ /** Install (or replace) the handler for an RBE_ effect name. */
254
+ register(name, handler) {
255
+ this.handlers.set(name, handler);
256
+ }
257
+ /** The handler currently installed, or null. Wrap by re-registering around it. */
258
+ handlerFor(name) {
259
+ return this.handlers.get(name) ?? null;
260
+ }
261
+ /** Whether anything answers for this effect name. */
262
+ has(name) {
263
+ return this.handlers.has(name);
264
+ }
265
+ /** Every registered effect name, in registration order. */
266
+ names() {
267
+ return [...this.handlers.keys()];
268
+ }
269
+ }
270
+ /**
271
+ * The registry used when a caller supplied none.
272
+ *
273
+ * This exists for the worldless harnesses and the direct-call tests, NOT as the
274
+ * game's registry: `wireGame` builds a fresh one per game and puts it on
275
+ * `GameState.blowEffects`, because a module-level singleton shared across games
276
+ * would let one game's mod leak into the next. A mod never reaches this one -
277
+ * the registry facade refuses to register when the host wired no registry, which
278
+ * is what stops "the mod registered and nothing read it".
279
+ */
280
+ let coreFallback = null;
281
+ function fallbackRegistry() {
282
+ if (coreFallback === null) {
283
+ coreFallback = new BlowEffectRegistry();
284
+ registerCoreBlowEffects(coreFallback);
285
+ }
286
+ return coreFallback;
287
+ }
236
288
  /**
237
289
  * Resolve one RBE_ blow effect: compute the HP damage the effect deals to the
238
290
  * player (context->damage after the handler runs) and record any timed /
239
291
  * stat / inventory / elemental side-effect intents.
292
+ *
293
+ * The message draw stays HERE rather than inside the handlers.
294
+ * `display_blow_message_vs_player` draws `randint0(num_messages)` before
295
+ * take_hit in every upstream handler, so hoisting it is what keeps the stream
296
+ * aligned - and it means a mod's handler cannot forget it and silently shift
297
+ * every subsequent roll.
240
298
  */
241
- function resolveBlowEffect(name, ctx) {
242
- const { rng, baseDamage, ac, rlev, phys } = ctx;
243
- const side = [];
244
- /* display_blow_message_vs_player draws randint0(num_messages) before take_hit
245
- * in every handler; hoisted here for the worldless path (no-op for the single-
246
- * message methods, first RNG event for the INSULT / MOAN effects). */
299
+ function resolveBlowEffect(name, ctx, registry = fallbackRegistry()) {
247
300
  drawBlowMessage(ctx);
248
- /* Elemental blows: physical component to HP; elemental component deferred. */
249
- if (name === "ACID" || name === "ELEC" || name === "FIRE" || name === "COLD") {
250
- const physical = phys ? adjustDamArmor(baseDamage, ac + 50) : 0;
251
- side.push({
252
- kind: "elemental",
253
- element: ELEMENT_OF_EFFECT[name],
254
- damage: baseDamage,
255
- });
256
- return { hpDamage: physical, obvious: true, sideEffects: side };
257
- }
258
- switch (name) {
259
- case "NONE":
260
- return { hpDamage: 0, obvious: true, sideEffects: side };
261
- case "HURT":
262
- return {
263
- hpDamage: adjustDamArmor(baseDamage, ac),
264
- obvious: true,
265
- sideEffects: side,
266
- };
267
- case "POISON": {
268
- const physical = phys ? adjustDamArmor(baseDamage, ac + 50) : 0;
269
- side.push({ kind: "elemental", element: "POIS", damage: baseDamage });
270
- side.push({
271
- kind: "timed",
272
- effect: "POISONED",
273
- amount: 5 + rng.randint1(rlev),
274
- });
275
- return { hpDamage: physical, obvious: true, sideEffects: side };
276
- }
277
- case "DISENCHANT":
278
- side.push({ kind: "disenchant" });
279
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
280
- case "DRAIN_CHARGES":
281
- side.push({ kind: "drainCharges" });
282
- return { hpDamage: baseDamage, obvious: false, sideEffects: side };
283
- case "EAT_GOLD":
284
- side.push({ kind: "eatGold" });
285
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
286
- case "EAT_ITEM":
287
- side.push({ kind: "eatItem" });
288
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
289
- case "EAT_FOOD":
290
- side.push({ kind: "eatFood" });
291
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
292
- case "EAT_LIGHT":
293
- side.push({ kind: "eatLight" });
294
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
295
- case "BLIND":
296
- side.push({
297
- kind: "timed",
298
- effect: "BLIND",
299
- amount: 10 + rng.randint1(rlev),
300
- });
301
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
302
- case "CONFUSE":
303
- side.push({
304
- kind: "timed",
305
- effect: "CONFUSED",
306
- amount: 3 + rng.randint1(rlev),
307
- });
308
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
309
- case "TERRIFY":
310
- side.push({
311
- kind: "timed",
312
- effect: "AFRAID",
313
- amount: 3 + rng.randint1(rlev),
314
- });
315
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
316
- case "PARALYZE":
317
- side.push({
318
- kind: "timed",
319
- effect: "PARALYZED",
320
- amount: 3 + rng.randint1(rlev),
321
- });
322
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
323
- case "LOSE_STR":
324
- case "LOSE_INT":
325
- case "LOSE_WIS":
326
- case "LOSE_DEX":
327
- case "LOSE_CON":
328
- side.push({ kind: "drainStat", stat: STAT_OF_EFFECT[name] });
329
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
330
- case "LOSE_ALL":
331
- for (const stat of ["STR", "DEX", "CON", "INT", "WIS"]) {
332
- side.push({ kind: "drainStat", stat });
333
- }
334
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
335
- case "SHATTER": {
336
- const hp = adjustDamArmor(baseDamage, ac);
337
- /* monster_damage_target() returns immediately on death (mon-blows.c
338
- * L1095), before either SHATTER side-effect gate or its RNG draw. */
339
- if (ctx.willPlayerDie?.(hp)) {
340
- return { hpDamage: hp, obvious: true, sideEffects: side };
341
- }
342
- if (hp > 23) {
343
- side.push({ kind: "earthquake", radius: Math.trunc(hp / 12) });
344
- }
345
- if (hp > 100) {
346
- const value = hp - 100;
347
- if (rng.randint1(value) > 40) {
348
- side.push({ kind: "knockback", distance: 1 + Math.trunc(value / 40) });
349
- }
350
- }
351
- return { hpDamage: hp, obvious: true, sideEffects: side };
352
- }
353
- case "EXP_10":
354
- case "EXP_20":
355
- case "EXP_40":
356
- case "EXP_80": {
357
- const spec = EXP_DRAIN[name];
358
- /* damroll(N, 6) is evaluated as the handler's argument. */
359
- const amount = rng.damroll(spec.dice, 6);
360
- side.push({ kind: "loseExp", holdChance: spec.holdChance, amount });
361
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
362
- }
363
- case "HALLU":
364
- side.push({
365
- kind: "timed",
366
- effect: "IMAGE",
367
- amount: 3 + rng.randint1(Math.trunc(rlev / 2)),
368
- });
369
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
370
- case "BLACK_BREATH":
371
- if (rng.oneIn(5)) {
372
- side.push({
373
- kind: "timed",
374
- effect: "BLACKBREATH",
375
- amount: Math.trunc(baseDamage / 10),
376
- });
377
- }
378
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
379
- default:
380
- /* Unknown effect: deal the base damage, as the fallthrough would. */
381
- return { hpDamage: baseDamage, obvious: true, sideEffects: side };
382
- }
301
+ const handler = registry.handlerFor(name);
302
+ if (handler !== null)
303
+ return handler.record(ctx);
304
+ /* Unknown effect: deal the base damage, as the fallthrough would. Upstream
305
+ * reports "ERROR: Effect handler not found" here (mon-attack.c:650); a
306
+ * mod-added blow_effects record with no registered handler lands on this. */
307
+ return { hpDamage: ctx.baseDamage, obvious: true, sideEffects: [] };
383
308
  }
384
309
  /**
385
310
  * melee_handler_for_blow_effect (mon-blows.c:1191): upstream's name -> handler
@@ -484,211 +409,406 @@ function applyElemental(env, name, ctx, pure) {
484
409
  * and context->blinked. The PARALYZE damage=1 pre-clamp is applied by the
485
410
  * caller before this runs (mon-blows.c L1020).
486
411
  */
487
- function resolveBlowEffectLive(name, ctx, env) {
488
- const { rng, baseDamage, ac, rlev } = ctx;
489
- const done = (contextDamage, reducedDamage, blinked = false) => ({ contextDamage, reducedDamage, obvious: true, blinked });
490
- /* Elemental blows (pure). */
491
- if (name === "ACID" || name === "ELEC" || name === "FIRE" || name === "COLD") {
492
- const r = applyElemental(env, name, ctx, true);
493
- return done(r.contextDamage, r.reducedDamage);
494
- }
495
- switch (name) {
496
- case "NONE":
497
- /* melee_effect_handler_NONE (mon-blows.c L638): show the message (with
498
- * its randint0(num_messages) draw) for a no-damage hit; no take_hit. */
412
+ function resolveBlowEffectLive(name, ctx, env, registry = fallbackRegistry()) {
413
+ const handler = registry.handlerFor(name);
414
+ if (handler !== null)
415
+ return handler.live(ctx, env);
416
+ /* Unknown effect: deal the base damage, as the fallthrough would. */
417
+ const reduced = env.applyReduction(ctx.baseDamage);
418
+ emitBlowMessageLive(env, ctx, reduced);
419
+ env.takeHit(reduced);
420
+ return {
421
+ contextDamage: ctx.baseDamage,
422
+ reducedDamage: reduced,
423
+ obvious: true,
424
+ blinked: false,
425
+ };
426
+ }
427
+ /* ------------------------------------------------------------------ *
428
+ * Core's 30 handlers
429
+ * ------------------------------------------------------------------ */
430
+ /** The shape every live handler returns; `blinked` defaults false. */
431
+ function live(contextDamage, reducedDamage, blinked = false) {
432
+ return { contextDamage, reducedDamage, obvious: true, blinked };
433
+ }
434
+ /**
435
+ * The damage-then-consequence sequence almost every mon-blows.c handler runs:
436
+ * reduce, show the message, take the hit, and do the rest only if the player
437
+ * survived. Factored out because it was written 20 times in the old switch and
438
+ * a divergence in any copy would have been invisible.
439
+ *
440
+ * `damage` is context->damage BEFORE player_apply_damage_reduction, which is
441
+ * what the cut/stun critical is computed from - not the HP actually lost.
442
+ */
443
+ function hitThen(ctx, env, damage, after) {
444
+ const reduced = env.applyReduction(damage);
445
+ emitBlowMessageLive(env, ctx, reduced);
446
+ env.takeHit(reduced);
447
+ if (env.playerDied)
448
+ return live(damage, reduced);
449
+ return live(damage, reduced, after?.(damage) === true);
450
+ }
451
+ /**
452
+ * Seed a registry with the 30 handlers upstream ships
453
+ * (`melee_handler_for_blow_effect`, mon-blows.c:1197-1226).
454
+ *
455
+ * These bodies are the two switch statements this registry replaced, lifted
456
+ * case by case with nothing rewritten - the RNG draws sit exactly where they
457
+ * sat, including the places where the two paths disagree about ORDER. BLIND is
458
+ * the clearest: the recording path draws the message first and the duration
459
+ * second, the live path draws the duration first. That is a port wart, it is
460
+ * observable through a multi-message method like INSULT, and core keeps its
461
+ * warts. `blow-vectors.json` is what proves none of them moved.
462
+ */
463
+ export function registerCoreBlowEffects(registry) {
464
+ const r = (name, handler) => registry.register(name, handler);
465
+ r("NONE", {
466
+ record: () => ({ hpDamage: 0, obvious: true, sideEffects: [] }),
467
+ /* melee_effect_handler_NONE (mon-blows.c L638): show the message (with its
468
+ * randint0(num_messages) draw) for a no-damage hit; no take_hit. */
469
+ live: (ctx, env) => {
499
470
  emitBlowMessageLive(env, ctx, 0);
500
- return done(0, 0);
501
- case "HURT": {
502
- const cd = adjustDamArmor(baseDamage, ac);
503
- const reduced = env.applyReduction(cd);
504
- emitBlowMessageLive(env, ctx, reduced);
505
- env.takeHit(reduced);
506
- return done(cd, reduced);
507
- }
508
- case "POISON": {
509
- const r = applyElemental(env, name, ctx, false);
471
+ return live(0, 0);
472
+ },
473
+ });
474
+ r("HURT", {
475
+ record: (ctx) => ({
476
+ hpDamage: adjustDamArmor(ctx.baseDamage, ctx.ac),
477
+ obvious: true,
478
+ sideEffects: [],
479
+ }),
480
+ live: (ctx, env) => hitThen(ctx, env, adjustDamArmor(ctx.baseDamage, ctx.ac)),
481
+ });
482
+ /* The four pure elementals. On the WORLDLESS path the physical component
483
+ * becomes HP damage and the elemental component is recorded as an intent; the
484
+ * LIVE path applies adjust_dam, inven_damage and the resist check in full
485
+ * through applyElemental. */
486
+ for (const name of ["ACID", "ELEC", "FIRE", "COLD"]) {
487
+ r(name, {
488
+ record: (ctx) => ({
489
+ hpDamage: ctx.phys ? adjustDamArmor(ctx.baseDamage, ctx.ac + 50) : 0,
490
+ obvious: true,
491
+ sideEffects: [
492
+ {
493
+ kind: "elemental",
494
+ element: ELEMENT_OF_EFFECT[name],
495
+ damage: ctx.baseDamage,
496
+ },
497
+ ],
498
+ }),
499
+ live: (ctx, env) => {
500
+ const res = applyElemental(env, name, ctx, true);
501
+ return live(res.contextDamage, res.reducedDamage);
502
+ },
503
+ });
504
+ }
505
+ r("POISON", {
506
+ record: (ctx) => ({
507
+ hpDamage: ctx.phys ? adjustDamArmor(ctx.baseDamage, ctx.ac + 50) : 0,
508
+ obvious: true,
509
+ sideEffects: [
510
+ { kind: "elemental", element: "POIS", damage: ctx.baseDamage },
511
+ {
512
+ kind: "timed",
513
+ effect: "POISONED",
514
+ amount: 5 + ctx.rng.randint1(ctx.rlev),
515
+ },
516
+ ],
517
+ }),
518
+ live: (ctx, env) => {
519
+ const res = applyElemental(env, "POISON", ctx, false);
510
520
  if (!env.playerDied) {
511
521
  /* player_inc_timed(TMD_POISONED, 5 + randint1(rlev)). */
512
- env.incTimed(TMD.POISONED, 5 + rng.randint1(rlev), true);
522
+ env.incTimed(TMD.POISONED, 5 + ctx.rng.randint1(ctx.rlev), true);
513
523
  }
514
- return done(r.contextDamage, r.reducedDamage);
515
- }
516
- case "DISENCHANT": {
517
- const reduced = env.applyReduction(baseDamage);
518
- emitBlowMessageLive(env, ctx, reduced);
519
- env.takeHit(reduced);
520
- if (!env.playerDied && !env.resists(ELEM.DISEN))
524
+ return live(res.contextDamage, res.reducedDamage);
525
+ },
526
+ });
527
+ r("DISENCHANT", {
528
+ record: (ctx) => ({
529
+ hpDamage: ctx.baseDamage,
530
+ obvious: true,
531
+ sideEffects: [{ kind: "disenchant" }],
532
+ }),
533
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => {
534
+ if (!env.resists(ELEM.DISEN))
521
535
  env.disenchant();
522
- return done(baseDamage, reduced);
523
- }
524
- case "DRAIN_CHARGES": {
525
- const reduced = env.applyReduction(baseDamage);
526
- emitBlowMessageLive(env, ctx, reduced);
527
- env.takeHit(reduced);
528
- if (!env.playerDied)
529
- env.drainCharges(rlev);
530
- return done(baseDamage, reduced);
531
- }
532
- case "EAT_GOLD": {
533
- const reduced = env.applyReduction(baseDamage);
534
- emitBlowMessageLive(env, ctx, reduced);
535
- env.takeHit(reduced);
536
- if (env.playerDied)
537
- return done(baseDamage, reduced);
538
- const blinked = env.eatGold();
539
- return done(baseDamage, reduced, blinked);
540
- }
541
- case "EAT_ITEM": {
542
- /* monster_damage_target(context, false): returns only on death. */
543
- const reduced = env.applyReduction(baseDamage);
544
- emitBlowMessageLive(env, ctx, reduced);
545
- env.takeHit(reduced);
546
- if (env.playerDied)
547
- return done(baseDamage, reduced);
548
- const r = env.eatItem();
549
- return done(baseDamage, reduced, r.blinked);
550
- }
551
- case "EAT_FOOD": {
552
- const reduced = env.applyReduction(baseDamage);
553
- emitBlowMessageLive(env, ctx, reduced);
554
- env.takeHit(reduced);
555
- if (!env.playerDied)
556
- env.eatFood();
557
- return done(baseDamage, reduced);
558
- }
559
- case "EAT_LIGHT": {
560
- const reduced = env.applyReduction(baseDamage);
561
- emitBlowMessageLive(env, ctx, reduced);
562
- env.takeHit(reduced);
563
- if (!env.playerDied)
564
- env.eatLight();
565
- return done(baseDamage, reduced);
566
- }
567
- case "BLIND": {
568
- /* melee_effect_timed: duration arg drawn first, then damage, no save. */
569
- const amount = 10 + rng.randint1(rlev);
570
- const reduced = env.applyReduction(baseDamage);
571
- emitBlowMessageLive(env, ctx, reduced);
572
- env.takeHit(reduced);
573
- if (!env.playerDied)
574
- env.incTimed(TMD.BLIND, amount, true);
575
- return done(baseDamage, reduced);
576
- }
577
- case "CONFUSE": {
578
- const amount = 3 + rng.randint1(rlev);
579
- const reduced = env.applyReduction(baseDamage);
580
- emitBlowMessageLive(env, ctx, reduced);
581
- env.takeHit(reduced);
582
- if (!env.playerDied)
583
- env.incTimed(TMD.CONFUSED, amount, true);
584
- return done(baseDamage, reduced);
585
- }
586
- case "TERRIFY": {
587
- const amount = 3 + rng.randint1(rlev);
588
- const reduced = env.applyReduction(baseDamage);
589
- emitBlowMessageLive(env, ctx, reduced);
590
- env.takeHit(reduced);
591
- if (!env.playerDied) {
592
- if (env.saveVsSkill())
593
- env.msg("You stand your ground!");
536
+ }),
537
+ });
538
+ r("DRAIN_CHARGES", {
539
+ record: (ctx) => ({
540
+ hpDamage: ctx.baseDamage,
541
+ obvious: false,
542
+ sideEffects: [{ kind: "drainCharges" }],
543
+ }),
544
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => env.drainCharges(ctx.rlev)),
545
+ });
546
+ r("EAT_GOLD", {
547
+ record: (ctx) => ({
548
+ hpDamage: ctx.baseDamage,
549
+ obvious: true,
550
+ sideEffects: [{ kind: "eatGold" }],
551
+ }),
552
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => env.eatGold()),
553
+ });
554
+ r("EAT_ITEM", {
555
+ record: (ctx) => ({
556
+ hpDamage: ctx.baseDamage,
557
+ obvious: true,
558
+ sideEffects: [{ kind: "eatItem" }],
559
+ }),
560
+ /* monster_damage_target(context, false): returns only on death. */
561
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => env.eatItem().blinked),
562
+ });
563
+ r("EAT_FOOD", {
564
+ record: (ctx) => ({
565
+ hpDamage: ctx.baseDamage,
566
+ obvious: true,
567
+ sideEffects: [{ kind: "eatFood" }],
568
+ }),
569
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => env.eatFood()),
570
+ });
571
+ r("EAT_LIGHT", {
572
+ record: (ctx) => ({
573
+ hpDamage: ctx.baseDamage,
574
+ obvious: true,
575
+ sideEffects: [{ kind: "eatLight" }],
576
+ }),
577
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => env.eatLight()),
578
+ });
579
+ /* melee_effect_timed: the duration argument is drawn BEFORE the damage on the
580
+ * live path, and AFTER the message on the recording path. Two of these take a
581
+ * saving throw first; the other two do not. */
582
+ const timed = (name, intent, tmd, amount, save) => r(name, {
583
+ record: (ctx) => ({
584
+ hpDamage: ctx.baseDamage,
585
+ obvious: true,
586
+ sideEffects: [{ kind: "timed", effect: intent, amount: amount(ctx) }],
587
+ }),
588
+ live: (ctx, env) => {
589
+ const dur = amount(ctx);
590
+ return hitThen(ctx, env, ctx.baseDamage, () => {
591
+ if (save !== undefined && env.saveVsSkill())
592
+ env.msg(save);
594
593
  else
595
- env.incTimed(TMD.AFRAID, amount, true);
596
- }
597
- return done(baseDamage, reduced);
598
- }
599
- case "PARALYZE": {
600
- const amount = 3 + rng.randint1(rlev);
601
- const reduced = env.applyReduction(baseDamage);
602
- emitBlowMessageLive(env, ctx, reduced);
603
- env.takeHit(reduced);
604
- if (!env.playerDied) {
605
- if (env.saveVsSkill())
606
- env.msg("You resist the effects!");
607
- else
608
- env.incTimed(TMD.PARALYZED, amount, true);
594
+ env.incTimed(tmd, dur, true);
595
+ });
596
+ },
597
+ });
598
+ timed("BLIND", "BLIND", TMD.BLIND, (ctx) => 10 + ctx.rng.randint1(ctx.rlev));
599
+ timed("CONFUSE", "CONFUSED", TMD.CONFUSED, (ctx) => 3 + ctx.rng.randint1(ctx.rlev));
600
+ timed("TERRIFY", "AFRAID", TMD.AFRAID, (ctx) => 3 + ctx.rng.randint1(ctx.rlev), "You stand your ground!");
601
+ timed("PARALYZE", "PARALYZED", TMD.PARALYZED, (ctx) => 3 + ctx.rng.randint1(ctx.rlev), "You resist the effects!");
602
+ for (const name of ["LOSE_STR", "LOSE_INT", "LOSE_WIS", "LOSE_DEX", "LOSE_CON"]) {
603
+ r(name, {
604
+ record: (ctx) => ({
605
+ hpDamage: ctx.baseDamage,
606
+ obvious: true,
607
+ sideEffects: [{ kind: "drainStat", stat: STAT_OF_EFFECT[name] }],
608
+ }),
609
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => env.drainStat(STAT_OF_LIVE_EFFECT[name])),
610
+ });
611
+ }
612
+ r("LOSE_ALL", {
613
+ record: (ctx) => ({
614
+ hpDamage: ctx.baseDamage,
615
+ obvious: true,
616
+ /* Upstream's order here is STR, DEX, CON, INT, WIS - not the STAT order. */
617
+ sideEffects: ["STR", "DEX", "CON", "INT", "WIS"].map((stat) => ({
618
+ kind: "drainStat",
619
+ stat,
620
+ })),
621
+ }),
622
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => {
623
+ env.drainStat(STAT.STR);
624
+ env.drainStat(STAT.DEX);
625
+ env.drainStat(STAT.CON);
626
+ env.drainStat(STAT.INT);
627
+ env.drainStat(STAT.WIS);
628
+ }),
629
+ });
630
+ r("SHATTER", {
631
+ record: (ctx) => {
632
+ const hp = adjustDamArmor(ctx.baseDamage, ctx.ac);
633
+ const side = [];
634
+ /* monster_damage_target() returns immediately on death (mon-blows.c
635
+ * L1095), before either SHATTER side-effect gate or its RNG draw. */
636
+ if (ctx.willPlayerDie?.(hp)) {
637
+ return { hpDamage: hp, obvious: true, sideEffects: side };
609
638
  }
610
- return done(baseDamage, reduced);
611
- }
612
- case "LOSE_STR":
613
- case "LOSE_INT":
614
- case "LOSE_WIS":
615
- case "LOSE_DEX":
616
- case "LOSE_CON": {
617
- const reduced = env.applyReduction(baseDamage);
618
- emitBlowMessageLive(env, ctx, reduced);
619
- env.takeHit(reduced);
620
- if (!env.playerDied)
621
- env.drainStat(STAT_OF_LIVE_EFFECT[name]);
622
- return done(baseDamage, reduced);
623
- }
624
- case "LOSE_ALL": {
625
- const reduced = env.applyReduction(baseDamage);
626
- emitBlowMessageLive(env, ctx, reduced);
627
- env.takeHit(reduced);
628
- if (!env.playerDied) {
629
- env.drainStat(STAT.STR);
630
- env.drainStat(STAT.DEX);
631
- env.drainStat(STAT.CON);
632
- env.drainStat(STAT.INT);
633
- env.drainStat(STAT.WIS);
639
+ if (hp > 23)
640
+ side.push({ kind: "earthquake", radius: Math.trunc(hp / 12) });
641
+ if (hp > 100) {
642
+ const value = hp - 100;
643
+ if (ctx.rng.randint1(value) > 40) {
644
+ side.push({ kind: "knockback", distance: 1 + Math.trunc(value / 40) });
645
+ }
634
646
  }
635
- return done(baseDamage, reduced);
636
- }
637
- case "SHATTER": {
638
- const cd = adjustDamArmor(baseDamage, ac);
639
- const reduced = env.applyReduction(cd);
640
- emitBlowMessageLive(env, ctx, reduced);
641
- env.takeHit(reduced);
642
- if (env.playerDied)
643
- return done(cd, reduced);
647
+ return { hpDamage: hp, obvious: true, sideEffects: side };
648
+ },
649
+ live: (ctx, env) => hitThen(ctx, env, adjustDamArmor(ctx.baseDamage, ctx.ac), (cd) => {
644
650
  if (cd > 23)
645
651
  env.earthquake(Math.trunc(cd / 12));
646
652
  if (cd > 100) {
647
653
  const value = cd - 100;
648
- if (rng.randint1(value) > 40)
654
+ if (ctx.rng.randint1(value) > 40)
649
655
  env.thrust(1 + Math.trunc(value / 40));
650
656
  }
651
- return done(cd, reduced);
652
- }
653
- case "EXP_10":
654
- case "EXP_20":
655
- case "EXP_40":
656
- case "EXP_80": {
657
- const spec = EXP_DRAIN[name];
658
- /* damroll(N, 6) is evaluated as the handler's argument, before take_hit. */
659
- const drainAmount = rng.damroll(spec.dice, 6);
660
- const reduced = env.applyReduction(baseDamage);
661
- emitBlowMessageLive(env, ctx, reduced);
662
- env.takeHit(reduced);
663
- if (!env.playerDied)
664
- env.drainExp(spec.holdChance, drainAmount);
665
- return done(baseDamage, reduced);
666
- }
667
- case "HALLU": {
668
- const reduced = env.applyReduction(baseDamage);
669
- emitBlowMessageLive(env, ctx, reduced);
670
- env.takeHit(reduced);
671
- if (!env.playerDied) {
672
- env.incTimed(TMD.IMAGE, 3 + rng.randint1(Math.trunc(rlev / 2)), true);
657
+ }),
658
+ });
659
+ for (const name of ["EXP_10", "EXP_20", "EXP_40", "EXP_80"]) {
660
+ const spec = EXP_DRAIN[name];
661
+ r(name, {
662
+ record: (ctx) => ({
663
+ hpDamage: ctx.baseDamage,
664
+ obvious: true,
665
+ /* damroll(N, 6) is evaluated as the handler's argument. */
666
+ sideEffects: [
667
+ {
668
+ kind: "loseExp",
669
+ holdChance: spec.holdChance,
670
+ amount: ctx.rng.damroll(spec.dice, 6),
671
+ },
672
+ ],
673
+ }),
674
+ live: (ctx, env) => {
675
+ /* ...which on the live path means BEFORE take_hit. */
676
+ const drainAmount = ctx.rng.damroll(spec.dice, 6);
677
+ return hitThen(ctx, env, ctx.baseDamage, () => env.drainExp(spec.holdChance, drainAmount));
678
+ },
679
+ });
680
+ }
681
+ r("HALLU", {
682
+ record: (ctx) => ({
683
+ hpDamage: ctx.baseDamage,
684
+ obvious: true,
685
+ sideEffects: [
686
+ {
687
+ kind: "timed",
688
+ effect: "IMAGE",
689
+ amount: 3 + ctx.rng.randint1(Math.trunc(ctx.rlev / 2)),
690
+ },
691
+ ],
692
+ }),
693
+ /* Unlike the other timed blows, HALLU draws its duration AFTER take_hit. */
694
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => {
695
+ env.incTimed(TMD.IMAGE, 3 + ctx.rng.randint1(Math.trunc(ctx.rlev / 2)), true);
696
+ }),
697
+ });
698
+ r("BLACK_BREATH", {
699
+ record: (ctx) => ({
700
+ hpDamage: ctx.baseDamage,
701
+ obvious: true,
702
+ sideEffects: ctx.rng.oneIn(5)
703
+ ? [
704
+ {
705
+ kind: "timed",
706
+ effect: "BLACKBREATH",
707
+ amount: Math.trunc(ctx.baseDamage / 10),
708
+ },
709
+ ]
710
+ : [],
711
+ }),
712
+ live: (ctx, env) => hitThen(ctx, env, ctx.baseDamage, () => {
713
+ if (ctx.rng.oneIn(5)) {
714
+ env.incTimed(TMD.BLACKBREATH, Math.trunc(ctx.baseDamage / 10), false);
673
715
  }
674
- return done(baseDamage, reduced);
675
- }
676
- case "BLACK_BREATH": {
677
- const reduced = env.applyReduction(baseDamage);
678
- emitBlowMessageLive(env, ctx, reduced);
679
- env.takeHit(reduced);
680
- if (!env.playerDied && rng.oneIn(5)) {
681
- env.incTimed(TMD.BLACKBREATH, Math.trunc(baseDamage / 10), false);
716
+ }),
717
+ });
718
+ }
719
+ /**
720
+ * Build a handler from a spec, so a mod writes its effect once.
721
+ *
722
+ * The live half applies each described side effect through the env with
723
+ * `applyBlowSideEffect`, which is the same vocabulary the worldless path
724
+ * records. A mod that describes "poison the player for 2d6 turns" therefore
725
+ * gets a recorded intent in the harness and a real `player_inc_timed` in the
726
+ * game, from one line, with no chance of the two disagreeing.
727
+ */
728
+ export function blowEffect(spec) {
729
+ const damageOf = (ctx) => spec.damage ? spec.damage(ctx) : ctx.baseDamage;
730
+ const obvious = spec.obvious ?? true;
731
+ return {
732
+ record: (ctx) => {
733
+ const damage = damageOf(ctx);
734
+ const before = spec.before ? [...spec.before(ctx)] : [];
735
+ /* The worldless path has no HP model of its own, so "did the player
736
+ * survive" is the caller's willPlayerDie, the same gate SHATTER uses. */
737
+ const died = ctx.willPlayerDie?.(damage) === true;
738
+ const after = died || !spec.after ? [] : [...spec.after(ctx)];
739
+ return { hpDamage: damage, obvious, sideEffects: [...before, ...after] };
740
+ },
741
+ live: (ctx, env) => {
742
+ const damage = damageOf(ctx);
743
+ const before = spec.before ? [...spec.before(ctx)] : [];
744
+ const result = hitThen(ctx, env, damage, () => {
745
+ let blinked = false;
746
+ for (const effect of [...before, ...(spec.after?.(ctx) ?? [])]) {
747
+ if (applyBlowSideEffect(env, effect))
748
+ blinked = true;
749
+ if (env.playerDied)
750
+ break;
751
+ }
752
+ return blinked;
753
+ });
754
+ return { ...result, obvious };
755
+ },
756
+ };
757
+ }
758
+ /**
759
+ * Apply one recorded side-effect intent to the world. Returns whether it blinked
760
+ * the monster away (context->blinked), which only the two thefts do.
761
+ *
762
+ * This is what makes `BlowSideEffect` a shared VOCABULARY rather than a
763
+ * worldless-only log: the same value that gets recorded in the harness is the
764
+ * one that gets applied in the game.
765
+ */
766
+ export function applyBlowSideEffect(env, effect) {
767
+ switch (effect.kind) {
768
+ case "timed": {
769
+ const tmd = TMD[effect.effect];
770
+ if (tmd !== undefined)
771
+ env.incTimed(tmd, effect.amount, true);
772
+ return false;
773
+ }
774
+ case "drainStat": {
775
+ const stat = STAT[effect.stat];
776
+ if (stat !== undefined)
777
+ env.drainStat(stat);
778
+ return false;
779
+ }
780
+ case "loseExp":
781
+ env.drainExp(effect.holdChance, effect.amount);
782
+ return false;
783
+ case "drainCharges":
784
+ env.drainCharges(0);
785
+ return false;
786
+ case "eatGold":
787
+ return env.eatGold();
788
+ case "eatItem":
789
+ return env.eatItem().blinked;
790
+ case "eatFood":
791
+ env.eatFood();
792
+ return false;
793
+ case "eatLight":
794
+ env.eatLight();
795
+ return false;
796
+ case "disenchant":
797
+ env.disenchant();
798
+ return false;
799
+ case "elemental": {
800
+ const elem = ELEM[effect.element];
801
+ if (elem !== undefined) {
802
+ env.invenDamage(elem, Math.min(effect.damage * 5, 300));
682
803
  }
683
- return done(baseDamage, reduced);
684
- }
685
- default: {
686
- /* Unknown effect: deal the base damage, as the fallthrough would. */
687
- const reduced = env.applyReduction(baseDamage);
688
- emitBlowMessageLive(env, ctx, reduced);
689
- env.takeHit(reduced);
690
- return done(baseDamage, reduced);
691
- }
804
+ return false;
805
+ }
806
+ case "earthquake":
807
+ env.earthquake(effect.radius);
808
+ return false;
809
+ case "knockback":
810
+ env.thrust(effect.distance);
811
+ return false;
692
812
  }
693
813
  }
694
814
  /* ------------------------------------------------------------------ *
@@ -739,6 +859,10 @@ export function monMeleeAttack(rng, mon, defender, def, opts = {}) {
739
859
  /* Visible monster missed the player: announce it (mon-attack.c L718). No
740
860
  * RNG is drawn; unseen monsters and no-miss methods stay silent. */
741
861
  if (env && env.monVisible && blow.method.miss) {
862
+ /* disturb(p) before the line (mon-attack.c L719-721): a MISS the player
863
+ * can see is still news, and stops a run or a rest. Nothing here reduces
864
+ * HP, so take_hit's own disturb cannot stand in for it. */
865
+ env.disturb?.();
742
866
  env.msg(`${env.monName} misses you.`);
743
867
  }
744
868
  blows.push({
@@ -751,6 +875,13 @@ export function monMeleeAttack(rng, mon, defender, def, opts = {}) {
751
875
  });
752
876
  continue;
753
877
  }
878
+ /* "Always disturbing" (mon-attack.c L593-594): the blow CONNECTED, so the
879
+ * player is disturbed before anything else happens - before protection from
880
+ * evil, before the damage roll, and regardless of whether the blow ends up
881
+ * doing any damage at all. take_hit's disturb (player-util.c:207) covers only
882
+ * the damaging blows; a 0-damage effect blow like BLIND or a repelled evil
883
+ * monster is disturbing here and nowhere else. */
884
+ env?.disturb?.();
754
885
  /* Apply "protection from evil" (mon-attack.c L597): an evil monster is
755
886
  * repelled on a high roll. The randint0(100) draw happens only when the
756
887
  * guard conditions hold, matching the C short-circuit order. */
@@ -795,7 +926,7 @@ export function monMeleeAttack(rng, mon, defender, def, opts = {}) {
795
926
  let obvious;
796
927
  const blowSide = [];
797
928
  if (env) {
798
- const res = resolveBlowEffectLive(effectName, blowCtx, env);
929
+ const res = resolveBlowEffectLive(effectName, blowCtx, env, opts.blowEffects);
799
930
  contextDamage = res.contextDamage;
800
931
  dealtDamage = res.reducedDamage;
801
932
  obvious = res.obvious;
@@ -807,7 +938,7 @@ export function monMeleeAttack(rng, mon, defender, def, opts = {}) {
807
938
  playerDied = true;
808
939
  }
809
940
  else {
810
- const res = resolveBlowEffect(effectName, blowCtx);
941
+ const res = resolveBlowEffect(effectName, blowCtx, opts.blowEffects);
811
942
  contextDamage = res.hpDamage;
812
943
  dealtDamage = res.hpDamage;
813
944
  obvious = res.obvious;