@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,1522 @@
1
+ /**
2
+ * Player calculation tables and helpers, ported VERBATIM from
3
+ * reference/src/player-calcs.c and player-util.c (Angband 4.2.6).
4
+ *
5
+ * The adj_* arrays are the stat-adjustment tables indexed by state->stat_ind
6
+ * (0..STAT_RANGE-1). Each has exactly STAT_RANGE (38) entries. blows_table is
7
+ * the 12x12 blow-energy table; player_exp is the experience needed per level.
8
+ *
9
+ * This module also ports the innate (race/class/stat/level) portion of
10
+ * calc_bonuses as calcBonuses, calc_blows as the pure calcBlows, plus
11
+ * player_flags (player.c), adjust_skill_scale and weight_limit, and the
12
+ * level-1 hitpoint math. The equipment analysis loop and the launcher /
13
+ * weapon analysis ARE ported: pass the worn objects via
14
+ * CalcBonusesOptions.equipment and calc_bonuses applies their stat, skill,
15
+ * combat and resist contributions and derives blows from the wielded weapon.
16
+ * calc_light and the timed effects (food, stun, bless, hero, shero,
17
+ * fast/slow, temp resists, etc.) are now ported (calcLight + the
18
+ * timedEffects-gated blocks in calcBonuses). The per-object curse-object
19
+ * traversal inside the equipment loop (2009-2023) is now ported: a worn item's
20
+ * active curses fold their template objects into the state (pass the bound
21
+ * Curse registry via CalcBonusesOptions.curses). Still DEFERRED (see the
22
+ * calcBonuses notes and parity/ledger/player-calcs-bonuses.yaml):
23
+ * - the learn-by-use rune system that populates obj_k (equipment modifiers
24
+ * are rune-gated and inert at birth)
25
+ * calc_mana (player-calcs.c:2322) is ported (player/spell.ts calcMana) and
26
+ * invoked by the session layer (session/game.ts) right after this pass, split
27
+ * across the calc/session seam; msp is populated there.
28
+ * calc_shapechange is now ported (a non-normal player.shape stacks its
29
+ * combat/skill/flag/modifier/resist package on the state).
30
+ */
31
+
32
+ import {
33
+ OF_SIZE,
34
+ PF_SIZE,
35
+ PY_MAX_LEVEL,
36
+ SKILL,
37
+ SKILL_MAX,
38
+ STAT_MAX,
39
+ STAT_RANGE,
40
+ TMD_MAX,
41
+ } from "./types.js";
42
+ import { ELEM, KF, OBJ_MOD, OF, PF, STAT, TMD, TV } from "../generated/index.js";
43
+ import { COLOUR_L_GREEN, COLOUR_RED, COLOUR_YELLOW } from "../color.js";
44
+ import { FlagSet } from "../bitflag.js";
45
+ import type {
46
+ PlayerClass,
47
+ PlayerElementInfo,
48
+ PlayerRace,
49
+ TimedEffect,
50
+ } from "./types.js";
51
+ import type { Player } from "./player.js";
52
+ import type { GameObject } from "../obj/object.js";
53
+ import type { Curse, ElementInfo } from "../obj/types.js";
54
+ import {
55
+ tvalCanHaveFlavor,
56
+ tvalIsAmmo,
57
+ tvalIsDigger,
58
+ tvalIsLight,
59
+ } from "../obj/object.js";
60
+ import { playerTimedGradeEq } from "./timed.js";
61
+ import type { PlayerCombatState } from "../combat/melee.js";
62
+ import type { DefenderState } from "../combat/mon-melee.js";
63
+
64
+ /* ------------------------------------------------------------------ */
65
+ /* Stat adjustment tables (player-calcs.c), each STAT_RANGE entries */
66
+ /* ------------------------------------------------------------------ */
67
+
68
+ /** Stat Table (INT) -- Magic devices. */
69
+ export const adj_int_dev: readonly number[] = [
70
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6,
71
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13,
72
+ ];
73
+
74
+ /** Stat Table (WIS) -- Saving throw. */
75
+ export const adj_wis_sav: readonly number[] = [
76
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 7,
77
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
78
+ ];
79
+
80
+ /** Stat Table (DEX) -- disarming. */
81
+ export const adj_dex_dis: readonly number[] = [
82
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10,
83
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19,
84
+ ];
85
+
86
+ /** Stat Table (INT) -- disarming. */
87
+ export const adj_int_dis: readonly number[] = [
88
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10,
89
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19,
90
+ ];
91
+
92
+ /** Stat Table (DEX) -- bonus to ac. */
93
+ export const adj_dex_ta: readonly number[] = [
94
+ -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5,
95
+ 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 15, 15,
96
+ ];
97
+
98
+ /** Stat Table (STR) -- bonus to dam. */
99
+ export const adj_str_td: readonly number[] = [
100
+ -2, -2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 5, 5,
101
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20,
102
+ ];
103
+
104
+ /** Stat Table (DEX) -- bonus to hit. */
105
+ export const adj_dex_th: readonly number[] = [
106
+ -3, -2, -2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5,
107
+ 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 15, 15,
108
+ ];
109
+
110
+ /** Stat Table (STR) -- bonus to hit. */
111
+ export const adj_str_th: readonly number[] = [
112
+ -3, -2, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4,
113
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15,
114
+ ];
115
+
116
+ /** Stat Table (STR) -- weight limit in deca-pounds. */
117
+ export const adj_str_wgt: readonly number[] = [
118
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, 26, 28, 30,
119
+ 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
120
+ ];
121
+
122
+ /** Stat Table (STR) -- weapon weight limit in pounds. */
123
+ export const adj_str_hold: readonly number[] = [
124
+ 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 30, 35, 40, 45, 50,
125
+ 55, 60, 65, 70, 80, 80, 80, 80, 80, 90, 90, 90, 90, 90, 100, 100, 100,
126
+ ];
127
+
128
+ /** Stat Table (STR) -- digging value. */
129
+ export const adj_str_dig: readonly number[] = [
130
+ 0, 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 12, 15, 20, 25, 30, 35, 40,
131
+ 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 100, 100,
132
+ ];
133
+
134
+ /** Stat Table (STR) -- index into the "blow" table. */
135
+ export const adj_str_blow: readonly number[] = [
136
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 30, 40, 50, 60, 70,
137
+ 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230,
138
+ 240,
139
+ ];
140
+
141
+ /** Stat Table (DEX) -- index into the "blow" table. */
142
+ export const adj_dex_blow: readonly number[] = [
143
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
144
+ 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11,
145
+ ];
146
+
147
+ /** Stat Table (DEX) -- chance of avoiding "theft" and "falling". */
148
+ export const adj_dex_safe: readonly number[] = [
149
+ 0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 15, 15, 20, 25, 30, 35,
150
+ 40, 45, 50, 60, 70, 80, 90, 100, 100, 100, 100, 100, 100, 100, 100,
151
+ ];
152
+
153
+ /** Stat Table (CON) -- base regeneration rate. */
154
+ export const adj_con_fix: readonly number[] = [
155
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4,
156
+ 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9,
157
+ ];
158
+
159
+ /** Stat Table (CON) -- extra 1/100th hitpoints per level. */
160
+ export const adj_con_mhp: readonly number[] = [
161
+ -250, -150, -100, -75, -50, -25, -10, -5, 0, 5, 10, 25, 50, 75, 100, 150, 175,
162
+ 200, 225, 250, 275, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800,
163
+ 900, 1000, 1100, 1250, 1250, 1250,
164
+ ];
165
+
166
+ /** Stat Table (INT/WIS) -- spell study rate. */
167
+ export const adj_mag_study: readonly number[] = [
168
+ 0, 0, 10, 20, 30, 40, 50, 60, 70, 80, 85, 90, 95, 100, 105, 110, 115, 120, 130,
169
+ 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 250, 250, 250, 250,
170
+ 250, 250, 250,
171
+ ];
172
+
173
+ /** Stat Table (INT/WIS) -- extra 1/100 mana-points per level. */
174
+ export const adj_mag_mana: readonly number[] = [
175
+ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170,
176
+ 180, 190, 200, 225, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800,
177
+ 800, 800, 800, 800,
178
+ ];
179
+
180
+ /**
181
+ * blows_table[P][D] (player-calcs.c): energy per blow indexed by the STR blow
182
+ * index P (adj_str_blow bucketed) and the DEX blow index D (adj_dex_blow).
183
+ */
184
+ export const blows_table: readonly (readonly number[])[] = [
185
+ [100, 100, 95, 85, 75, 60, 50, 42, 35, 30, 25, 23],
186
+ [100, 95, 85, 75, 60, 50, 42, 35, 30, 25, 23, 21],
187
+ [95, 85, 75, 60, 50, 42, 35, 30, 26, 23, 21, 20],
188
+ [85, 75, 60, 50, 42, 36, 32, 28, 25, 22, 20, 19],
189
+ [75, 60, 50, 42, 36, 33, 28, 25, 23, 21, 19, 18],
190
+ [60, 50, 42, 36, 33, 30, 27, 24, 22, 21, 19, 17],
191
+ [50, 42, 36, 33, 30, 27, 25, 23, 21, 20, 18, 17],
192
+ [42, 36, 33, 30, 28, 26, 24, 22, 20, 19, 18, 17],
193
+ [36, 33, 30, 28, 26, 24, 22, 21, 20, 19, 17, 16],
194
+ [35, 32, 29, 26, 24, 22, 21, 20, 19, 18, 17, 16],
195
+ [34, 30, 27, 25, 23, 22, 21, 20, 19, 18, 17, 16],
196
+ [33, 29, 26, 24, 22, 21, 20, 19, 18, 17, 16, 15],
197
+ ];
198
+
199
+ /**
200
+ * Experience needed to reach each level (player.c player_exp[PY_MAX_LEVEL]).
201
+ * player_exp[lev-1] is the base threshold for level lev+1; multiplied by the
202
+ * player's expfact/100.
203
+ */
204
+ export const player_exp: readonly number[] = [
205
+ 10, 25, 45, 70, 100, 140, 200, 280, 380, 500, 650, 850, 1100, 1400, 1800, 2300,
206
+ 2900, 3600, 4400, 5400, 6800, 8400, 10200, 12500, 17500, 25000, 35000, 50000,
207
+ 75000, 100000, 150000, 200000, 275000, 350000, 450000, 550000, 700000, 850000,
208
+ 1000000, 1250000, 1500000, 1800000, 2100000, 2400000, 2700000, 3000000, 3500000,
209
+ 4000000, 4500000, 5000000,
210
+ ];
211
+
212
+ /* ------------------------------------------------------------------ */
213
+ /* Helpers */
214
+ /* ------------------------------------------------------------------ */
215
+
216
+ /** Bounds-checked table read; throws on an out-of-range index. */
217
+ function at(table: readonly number[], i: number): number {
218
+ const v = table[i];
219
+ if (v === undefined) {
220
+ throw new Error(`player: adj table index out of range: ${i}`);
221
+ }
222
+ return v;
223
+ }
224
+
225
+ /**
226
+ * modify_stat_value (player-util.c): apply a racial/class stat modifier to a
227
+ * base stat value, using the 3..18/220 encoding (each point below 18 is +1,
228
+ * each point at/above 18 is +10; symmetric on the way down).
229
+ */
230
+ export function modifyStatValue(value: number, amount: number): number {
231
+ let v = value;
232
+ if (amount > 0) {
233
+ for (let i = 0; i < amount; i++) {
234
+ if (v < 18) v++;
235
+ else v += 10;
236
+ }
237
+ } else if (amount < 0) {
238
+ for (let i = 0; i < -amount; i++) {
239
+ if (v >= 18 + 10) v -= 10;
240
+ else if (v > 18) v = 18;
241
+ else if (v > 3) v--;
242
+ }
243
+ }
244
+ return v;
245
+ }
246
+
247
+ /**
248
+ * The stat_ind computation from calc_bonuses: map a modified stat "use" value
249
+ * to its index into the adj_* tables (0..STAT_RANGE-1).
250
+ */
251
+ export function statUseToIndex(use: number): number {
252
+ let ind: number;
253
+ if (use <= 3) ind = 0;
254
+ else if (use <= 18) ind = use - 3;
255
+ else if (use <= 18 + 219) ind = 15 + Math.trunc((use - 18) / 10);
256
+ else ind = 37;
257
+ if (ind < 0 || ind >= STAT_RANGE) {
258
+ throw new Error(`player: stat index out of range: ${ind}`);
259
+ }
260
+ return ind;
261
+ }
262
+
263
+ /**
264
+ * Compute the stat_ind array (indices into adj_* tables) for a race/class at a
265
+ * given set of base stat values (state->stat_ind in calc_bonuses, without the
266
+ * hypothetical-blow hack). stat_add (equipment) is DEFERRED and treated as 0.
267
+ */
268
+ export function calcStatIndices(
269
+ race: PlayerRace,
270
+ cls: PlayerClass,
271
+ statCur: readonly number[],
272
+ ): number[] {
273
+ const out = new Array<number>(STAT_MAX).fill(0);
274
+ for (let i = 0; i < STAT_MAX; i++) {
275
+ const add = (race.statAdj[i] ?? 0) + (cls.statAdj[i] ?? 0);
276
+ const use = modifyStatValue(statCur[i] ?? 0, add);
277
+ out[i] = statUseToIndex(use);
278
+ }
279
+ return out;
280
+ }
281
+
282
+ /**
283
+ * calc_hitpoints (player-calcs.c): maximum hitpoints at a level, given the
284
+ * accumulated player_hp roll for that level and the CON stat index.
285
+ * mhp = player_hp[lev-1] + adj_con_mhp[con_ind] * lev / 100, floored at lev+1.
286
+ */
287
+ export function calcHitpoints(
288
+ playerHpAtLevel: number,
289
+ lev: number,
290
+ conInd: number,
291
+ ): number {
292
+ const bonus = at(adj_con_mhp, conInd);
293
+ let mhp = playerHpAtLevel + Math.trunc((bonus * lev) / 100);
294
+ if (mhp < lev + 1) mhp = lev + 1;
295
+ return mhp;
296
+ }
297
+
298
+ /**
299
+ * The "Modify skills" tail of calc_bonuses (player-calcs.c:2239-2250),
300
+ * applied in the exact upstream statement order:
301
+ * DISARM_PHYS += adj_dex_dis[stat_ind[DEX]] (2240)
302
+ * DISARM_MAGIC += adj_int_dis[stat_ind[INT]] (2241)
303
+ * DEVICE += adj_int_dev[stat_ind[INT]] (2242)
304
+ * SAVE += adj_wis_sav[stat_ind[WIS]] (2243)
305
+ * DIGGING += adj_str_dig[stat_ind[STR]] (2244)
306
+ * skills[i] += x_skills[i] * lev / 10 (2245-2246)
307
+ * then DIGGING is floored at 1 and STEALTH clamped to [0, 30] (2248-2250).
308
+ */
309
+ function applySkillStatAndLevel(
310
+ skills: number[],
311
+ cls: PlayerClass,
312
+ lev: number,
313
+ statInd: readonly number[],
314
+ ): void {
315
+ skills[SKILL.DISARM_PHYS] =
316
+ (skills[SKILL.DISARM_PHYS] ?? 0) + at(adj_dex_dis, statInd[STAT.DEX] ?? 0);
317
+ skills[SKILL.DISARM_MAGIC] =
318
+ (skills[SKILL.DISARM_MAGIC] ?? 0) + at(adj_int_dis, statInd[STAT.INT] ?? 0);
319
+ skills[SKILL.DEVICE] =
320
+ (skills[SKILL.DEVICE] ?? 0) + at(adj_int_dev, statInd[STAT.INT] ?? 0);
321
+ skills[SKILL.SAVE] =
322
+ (skills[SKILL.SAVE] ?? 0) + at(adj_wis_sav, statInd[STAT.WIS] ?? 0);
323
+ skills[SKILL.DIGGING] =
324
+ (skills[SKILL.DIGGING] ?? 0) + at(adj_str_dig, statInd[STAT.STR] ?? 0);
325
+ for (let i = 0; i < SKILL_MAX; i++) {
326
+ skills[i] = (skills[i] ?? 0) + Math.trunc(((cls.extraSkills[i] ?? 0) * lev) / 10);
327
+ }
328
+ if ((skills[SKILL.DIGGING] ?? 0) < 1) skills[SKILL.DIGGING] = 1;
329
+ if ((skills[SKILL.STEALTH] ?? 0) > 30) skills[SKILL.STEALTH] = 30;
330
+ if ((skills[SKILL.STEALTH] ?? 0) < 0) skills[SKILL.STEALTH] = 0;
331
+ }
332
+
333
+ /**
334
+ * The non-equipment portion of calc_bonuses skill computation: base
335
+ * skills[i] = r_skills[i] + c_skills[i] (player-calcs.c:1904-1906) followed
336
+ * by the stat and level adjustments (2239-2250, see applySkillStatAndLevel).
337
+ * For a player with no equipment, no timed effects and the normal shape this
338
+ * equals calcBonuses(player).skills.
339
+ */
340
+ export function calcSkills(
341
+ race: PlayerRace,
342
+ cls: PlayerClass,
343
+ lev: number,
344
+ statInd: readonly number[],
345
+ ): number[] {
346
+ const skills = new Array<number>(SKILL_MAX).fill(0);
347
+ for (let i = 0; i < SKILL_MAX; i++) {
348
+ skills[i] = (race.skills[i] ?? 0) + (cls.skills[i] ?? 0);
349
+ }
350
+ applySkillStatAndLevel(skills, cls, lev, statInd);
351
+ return skills;
352
+ }
353
+
354
+ /* ------------------------------------------------------------------ */
355
+ /* Player state (calc_bonuses / calc_blows) */
356
+ /* ------------------------------------------------------------------ */
357
+
358
+ /**
359
+ * struct player_state (player.h:401-438): all the variable state that
360
+ * changes when equipment goes on or off. Field-for-field port; `hold` is
361
+ * additionally kept (upstream computes it as a local at player-calcs.c:2251)
362
+ * because the deferred launcher/weapon weight analysis will need it.
363
+ */
364
+ export interface PlayerState {
365
+ /** stat_add[STAT_MAX]: equipment stat bonuses (rune-gated, decision 25). */
366
+ statAdd: number[];
367
+ /** stat_ind[STAT_MAX]: indices into the adj_* stat tables. */
368
+ statInd: number[];
369
+ /** stat_use[STAT_MAX]: current modified stats. */
370
+ statUse: number[];
371
+ /** stat_top[STAT_MAX]: maximal modified stats. */
372
+ statTop: number[];
373
+ /** skills[SKILL_MAX], indexed by SKILL. */
374
+ skills: number[];
375
+ /** Current speed (110 = normal). */
376
+ speed: number;
377
+ /** Number of blows times 100. */
378
+ numBlows: number;
379
+ /** Number of shots times 10 (launcher DEFERRED: 0). */
380
+ numShots: number;
381
+ /** Number of extra movement actions. */
382
+ numMoves: number;
383
+ /** Ammo multiplier (launcher DEFERRED: 0). */
384
+ ammoMult: number;
385
+ /** Ammo variety, as an upstream tval number (launcher DEFERRED: 0). */
386
+ ammoTval: number;
387
+ /** Base ac (armour DEFERRED: 0). */
388
+ ac: number;
389
+ /** Damage reduction. */
390
+ damRed: number;
391
+ /** Percentage damage reduction. */
392
+ percDamRed: number;
393
+ /** Bonus to ac. */
394
+ toA: number;
395
+ /** Bonus to hit. */
396
+ toH: number;
397
+ /** Bonus to dam. */
398
+ toD: number;
399
+ /** Infravision range. */
400
+ seeInfra: number;
401
+ /** Radius of light (calc_light; 0 when no light source is wielded). */
402
+ curLight: number;
403
+ /** Heavy weapon (weapon analysis, player-calcs.c:2291-2319). */
404
+ heavyWield: boolean;
405
+ /** Heavy shooter (launcher analysis, player-calcs.c:2254-2288). */
406
+ heavyShoot: boolean;
407
+ /** Blessed (or blunt) weapon (weapon analysis, player-calcs.c:2291-2319). */
408
+ blessWield: boolean;
409
+ /** Mana draining armour: set by calcMana in the session layer, not here. */
410
+ cumberArmor: boolean;
411
+ /** Status flags from race and items (OF_*). */
412
+ flags: FlagSet;
413
+ /** Player intrinsic flags (PF_*). */
414
+ pflags: FlagSet;
415
+ /** Resists from race and items, length ELEM_MAX. */
416
+ elInfo: PlayerElementInfo[];
417
+ /** adj_str_hold[stat_ind[STR]] (local `hold` at player-calcs.c:2251). */
418
+ hold: number;
419
+ }
420
+
421
+ /**
422
+ * player_flags (player.c:290-300): the player's innate object flags -- racial
423
+ * flags unioned with class flags, plus OF_PROT_FEAR for PF_BRAVERY_30
424
+ * classes at level 30+. Returns a fresh OF-sized flag set (upstream fills a
425
+ * caller buffer).
426
+ */
427
+ export function playerFlags(player: Player): FlagSet {
428
+ const f = new FlagSet(OF_SIZE);
429
+ f.copy(player.race.flags);
430
+ f.union(player.cls.flags);
431
+ if (
432
+ (player.race.pflags.has(PF.BRAVERY_30) ||
433
+ player.cls.pflags.has(PF.BRAVERY_30)) &&
434
+ player.lev >= 30
435
+ ) {
436
+ f.on(OF.PROT_FEAR);
437
+ }
438
+ return f;
439
+ }
440
+
441
+ /**
442
+ * player_hp_attr (player.c:323): the colour the current hitpoints are drawn
443
+ * in - COLOUR_L_GREEN at full health, COLOUR_YELLOW while above the
444
+ * hitpoint-warning fraction (mhp * hitpoint_warn / 10), else COLOUR_RED.
445
+ * `hitpointWarn` is op_ptr->hitpoint_warn (0..9); the options store is
446
+ * deferred, so the caller supplies it.
447
+ */
448
+ export function playerHpAttr(
449
+ p: Pick<Player, "chp" | "mhp">,
450
+ hitpointWarn: number,
451
+ ): number {
452
+ if (p.chp >= p.mhp) return COLOUR_L_GREEN;
453
+ if (p.chp > Math.trunc((p.mhp * hitpointWarn) / 10)) return COLOUR_YELLOW;
454
+ return COLOUR_RED;
455
+ }
456
+
457
+ /**
458
+ * player_sp_attr (player.c:337): the spell-point colour, identical thresholds
459
+ * to player_hp_attr but on csp / msp.
460
+ */
461
+ export function playerSpAttr(
462
+ p: Pick<Player, "csp" | "msp">,
463
+ hitpointWarn: number,
464
+ ): number {
465
+ if (p.csp >= p.msp) return COLOUR_L_GREEN;
466
+ if (p.csp > Math.trunc((p.msp * hitpointWarn) / 10)) return COLOUR_YELLOW;
467
+ return COLOUR_RED;
468
+ }
469
+
470
+ /**
471
+ * adjust_skill_scale (player-calcs.c:1781-1792): adjust a value by a
472
+ * relative factor of its absolute value, mimicking value * (den + num) / den
473
+ * for positive values (negative num rounds the adjustment up). Returns the
474
+ * adjusted value instead of mutating through a pointer.
475
+ */
476
+ export function adjustSkillScale(
477
+ v: number,
478
+ num: number,
479
+ den: number,
480
+ minv: number,
481
+ ): number {
482
+ if (num >= 0) {
483
+ return v + Math.trunc((Math.max(minv, Math.abs(v)) * num) / den);
484
+ }
485
+ /* To mimic (value * (den + num)) / den for positive value, round up. */
486
+ return v - Math.trunc((Math.max(minv, Math.abs(v)) * -num + den - 1) / den);
487
+ }
488
+
489
+ /**
490
+ * weight_limit (player-calcs.c:1741-1750): the carrying capacity in tenth
491
+ * pounds, based only on strength.
492
+ */
493
+ export function weightLimit(state: PlayerState): number {
494
+ return at(adj_str_wgt, state.statInd[STAT.STR] ?? 0) * 100;
495
+ }
496
+
497
+ /**
498
+ * weight_remaining (player-calcs.c:1752-1765): tenth-pounds of carry capacity
499
+ * left before becoming burdened - `60 * adj_str_wgt[STR] - total_weight - 1`,
500
+ * which is NEGATIVE while there is room to spare (the character sheet prints
501
+ * `-diff/10`, so spare capacity shows as a negative "Overweight" figure, and
502
+ * real encumbrance shows as a positive one).
503
+ */
504
+ export function weightRemaining(state: PlayerState, totalWeight: number): number {
505
+ return 60 * at(adj_str_wgt, state.statInd[STAT.STR] ?? 0) - totalWeight - 1;
506
+ }
507
+
508
+ /**
509
+ * calc_blows (player-calcs.c:1703-1735): the blows a player would get with a
510
+ * weapon of the given weight, as a pure function of the class blow
511
+ * parameters and the STR/DEX stat indices (state->stat_ind upstream).
512
+ *
513
+ * \param cls supplies min_weight, att_multiply and max_attacks.
514
+ * \param weaponWeight is object_weight_one(obj) in tenth pounds, or null for
515
+ * no weapon (upstream passes obj == NULL and uses weight 0, so the class
516
+ * min_weight becomes the divisor).
517
+ * \param strInd / dexInd are stat_ind[STAT_STR] / stat_ind[STAT_DEX].
518
+ * \param extraBlows is the +blows total from gear and state (innately 0).
519
+ * \param percentDamage is OPT(p, birth_percent_damage): O-combat requires
520
+ * two blows minimum instead of one.
521
+ * \returns 100x the number of blows.
522
+ */
523
+ export function calcBlows(
524
+ cls: Pick<PlayerClass, "minWeight" | "attMultiply" | "maxAttacks">,
525
+ weaponWeight: number | null,
526
+ strInd: number,
527
+ dexInd: number,
528
+ extraBlows = 0,
529
+ percentDamage = false,
530
+ ): number {
531
+ const weight = weaponWeight === null ? 0 : weaponWeight;
532
+ const minWeight = cls.minWeight;
533
+
534
+ /* Enforce a minimum "weight" (tenth pounds) (1715). */
535
+ const div = weight < minWeight ? minWeight : weight;
536
+
537
+ /* Get the strength vs weight (1717-1722). */
538
+ let strIndex = Math.trunc((at(adj_str_blow, strInd) * cls.attMultiply) / div);
539
+ if (strIndex > 11) strIndex = 11;
540
+
541
+ /* Index by dexterity (1724-1725). */
542
+ const dexIndex = Math.min(at(adj_dex_blow, dexInd), 11);
543
+
544
+ /* Use the blows table to get energy per blow (1727-1730). */
545
+ const blowEnergy = blows_table[strIndex]?.[dexIndex];
546
+ if (blowEnergy === undefined) {
547
+ throw new Error(`player: blows_table index out of range: ${strIndex},${dexIndex}`);
548
+ }
549
+ const blows = Math.min(
550
+ Math.trunc(10000 / blowEnergy),
551
+ 100 * cls.maxAttacks,
552
+ );
553
+
554
+ /* Require at least one blow, two for O-combat (1732-1734). */
555
+ return Math.max(blows + 100 * extraBlows, percentDamage ? 200 : 100);
556
+ }
557
+
558
+ /** Options for calcBonuses covering upstream globals. */
559
+ export interface CalcBonusesOptions {
560
+ /**
561
+ * character_dungeon (upstream global): true once the character is in play
562
+ * on a generated level. Gates the PF_UNLIGHT / PF_EVIL element-info
563
+ * adjustments (player-calcs.c:2043-2052). Defaults to false (the
564
+ * freshly-born state).
565
+ */
566
+ characterDungeon?: boolean;
567
+ /**
568
+ * The equipped object per body slot (index = body slot, null = empty), as
569
+ * resolved from player.equipment via the gear store. Drives the equipment
570
+ * analysis loop (player-calcs.c:1924-2025) and the launcher / weapon
571
+ * analysis (2254-2319). Defaults to empty (unarmed and unarmored).
572
+ */
573
+ equipment?: readonly (GameObject | null)[];
574
+ /**
575
+ * The bound timed-effect table (player/bind.ts TimedEffect[]), indexed by
576
+ * TMD. Drives the FOOD-grade block (2094-2132), player_flags_timed and the
577
+ * grade / temp_resist driven timed block (2134-2213). Defaults to empty,
578
+ * which disables the whole timed model (both the table-driven AND the
579
+ * per-timer branches) so no self-inconsistent partial derive can occur:
580
+ * an empty table is valid only when the timed contributions are meant to
581
+ * be ignored wholesale (the innate / no-timers callers). All three live
582
+ * call sites (game.ts refreshDerived, startGame, loadGame) pass players.timed.
583
+ */
584
+ timedEffects?: readonly TimedEffect[];
585
+ /**
586
+ * The bound curse registry (obj/bind.ts (Curse | null)[], 1-based, index 0
587
+ * null), i.e. upstream's global `curses[]` array of length z_info->curse_max.
588
+ * Drives the per-object curse-object traversal in the equipment loop
589
+ * (player-calcs.c:2009-2023): each worn item's active curses fold their own
590
+ * curse template object (modifiers/flags/toH/toD/toA/elInfo) into the state.
591
+ * Defaults to empty, which disables the traversal (no templates to resolve);
592
+ * the live call sites (game.ts refreshDerived/startGame/loadGame) pass
593
+ * reg.objects.curses.
594
+ */
595
+ curses?: readonly (Curse | null)[];
596
+ /**
597
+ * calc_bonuses' `update` arg (player-calcs.c:1877): when true the derive is
598
+ * allowed its faithful side effects -- zeroing p->timed[TMD_FASTCAST] on a
599
+ * Stun/Heavy Stun grade (2141-2143/2148-2150) and the calc_light town
600
+ * redraw flag. Defaults to true (the live refresh path). Hypothetical /
601
+ * known_only callers pass false so the derive stays pure.
602
+ */
603
+ update?: boolean;
604
+ /**
605
+ * The hypothetical-blows stat-index shift (player-calcs.c:2077-2088), the
606
+ * "Hack for hypothetical blows - NRM" upstream runs when update is false and
607
+ * a caller has pre-loaded state->stat_ind[STAT_STR]/[STAT_DEX] with an
608
+ * increment. obj-info.c's obj_known_blows / obj_known_damage / obj_known_digging
609
+ * / obj_known_misc_combat all take this path (they zero the two indices, then
610
+ * the blows scan bumps them). When supplied, the STR and DEX stat indices are
611
+ * shifted by str / dex and clamped to [3, 37] AFTER the normal derivation,
612
+ * exactly as upstream. Absent (the live refresh path), no shift is applied.
613
+ */
614
+ statIndBoost?: { str: number; dex: number };
615
+ /**
616
+ * p->depth (calc_light town-daytime early-out, 1607). Defaults to undefined,
617
+ * treated as a nonzero depth so the town branch stays dormant.
618
+ */
619
+ depth?: number;
620
+ /**
621
+ * is_daytime() (calc_light, 1607). Defaults to false; the town-daytime
622
+ * early-out is dormant until the world clock lands (see calcLight).
623
+ */
624
+ isDaytime?: boolean;
625
+ }
626
+
627
+ /**
628
+ * calc_light (player-calcs.c:1598-1645): set state.curLight to the sum of the
629
+ * light radii of every wielded light source. Each slot contributes OF_LIGHT_2
630
+ * (2) or OF_LIGHT_3 (3) plus its OBJ_MOD_LIGHT modifier, an UNLIGHT player
631
+ * loses 1 from any positive +LIGHT item, and a tval-light item with fuel that
632
+ * has run out (timeout == 0, no NO_FUEL) contributes nothing.
633
+ *
634
+ * FAITHFULNESS: obj->modifiers[OBJ_MOD_LIGHT] is read RAW here (1629), NOT
635
+ * multiplied by the learned-rune mask obj_k like the pval modifiers in the
636
+ * equipment loop -- upstream calc_light does not rune-gate light. Do not
637
+ * "consistency-fix" this into a knownMods multiply; that would diverge.
638
+ */
639
+ function calcLight(
640
+ player: Player,
641
+ state: PlayerState,
642
+ options: CalcBonusesOptions,
643
+ ): void {
644
+ /* Assume no light (1604). */
645
+ state.curLight = 0;
646
+
647
+ /* Ascertain lightness if in the town (1606-1613). is_daytime() comes from
648
+ the world clock (deferred), so isDaytime defaults false and this branch
649
+ is dormant in the dungeon-only build.
650
+ TODO(world-clock): when isDaytime becomes real, also reinstate the
651
+ upstream visual refresh here -- calc_light sets p->upkeep->update |=
652
+ (PU_UPDATE_VIEW | PU_MONSTERS) when the town light changes (1608-1611)
653
+ before returning. The port must trigger the equivalent view/monster
654
+ refresh on the town daytime path once the town/world clock lands. */
655
+ const depth = options.depth;
656
+ const update = options.update ?? true;
657
+ if (depth === 0 && (options.isDaytime ?? false) && update) {
658
+ return;
659
+ }
660
+
661
+ const equipment = options.equipment ?? [];
662
+
663
+ /* Examine all wielded objects, use the brightest (1615-1644). */
664
+ for (let i = 0; i < player.body.count; i++) {
665
+ let amt = 0;
666
+ const obj = equipment[i] ?? null;
667
+
668
+ /* Skip empty slots (1621). */
669
+ if (!obj) continue;
670
+
671
+ /* Light radius - innate plus modifier (1623-1629). */
672
+ if (obj.flags.has(OF.LIGHT_2)) {
673
+ amt = 2;
674
+ } else if (obj.flags.has(OF.LIGHT_3)) {
675
+ amt = 3;
676
+ }
677
+ amt += obj.modifiers[OBJ_MOD.LIGHT] ?? 0;
678
+
679
+ /* Adjustment to allow UNLIGHT players to use +1 LIGHT gear (1631-1634). */
680
+ if ((obj.modifiers[OBJ_MOD.LIGHT] ?? 0) > 0 && state.pflags.has(PF.UNLIGHT)) {
681
+ amt--;
682
+ }
683
+
684
+ /* Examine actual lights: no fuel means no light (1636-1640). */
685
+ if (tvalIsLight(obj.tval) && !obj.flags.has(OF.NO_FUEL) && obj.timeout === 0) {
686
+ amt = 0;
687
+ }
688
+
689
+ /* Alter cur_light if reasonable (1643). */
690
+ state.curLight += amt;
691
+ }
692
+ }
693
+
694
+ /**
695
+ * calc_bonuses (player-calcs.c:1877-2331), innate portion: derives the
696
+ * player's state from race/class intrinsics, stats, level, the worn
697
+ * equipment (options.equipment) and the timed effects (options.timedEffects
698
+ * + player.timed). With no equipment supplied the player is unarmed and
699
+ * unarmored (the just-born default); with no timed table supplied the timed
700
+ * model is inert (see CalcBonusesOptions.timedEffects).
701
+ *
702
+ * Ported statement-for-statement in upstream order; each block cites its
703
+ * lines. DEFERRED blocks (see parity/ledger/player-calcs-bonuses.yaml), all
704
+ * of which are no-ops for the innate state:
705
+ * - the learn-by-use rune system that populates obj_k: equipment modifiers
706
+ * are rune-gated (obj->modifiers * obj_k->modifiers) and UNKNOWN at birth
707
+ * (decision 25), so they contribute nothing until a rune is learned. The
708
+ * per-object curse-object traversal in the equipment loop (2009-2023) is
709
+ * now ported (see options.curses)
710
+ * - calc_light (2040-2041), the food-grade block (2094-2132) and the timed
711
+ * block (2134-2213) are now ported (calcLight + the timedEffects-gated
712
+ * blocks below); the launcher analysis (2254-2288) and weapon analysis
713
+ * (2291-2319) are ported and the wielded weapon drives num_blows/digging
714
+ * - calc_mana (2322): ported (player/spell.ts calcMana) but called by the
715
+ * session layer just after this pass, not inline; the PF_NO_MANA check
716
+ * (2323-2325) is ported here and reads p->msp populated by that call
717
+ * - the known_only object-knowledge variant and the !update hypothetical
718
+ * blows index shift (1891-1893, 2077-2088): birth-UI only
719
+ */
720
+ export function calcBonuses(
721
+ player: Player,
722
+ options: CalcBonusesOptions = {},
723
+ ): PlayerState {
724
+ const race = player.race;
725
+ const cls = player.cls;
726
+ const elemCount = race.elInfo.length;
727
+ /* extra_blows/shots/might/moves accumulate from equipment modifiers and
728
+ feed the launcher / weapon / movement analysis below (0 when unarmed). */
729
+ let extraBlows = 0;
730
+ let extraShots = 0;
731
+ let extraMight = 0;
732
+ let extraMoves = 0;
733
+ /* The wielded weapon and launcher, captured during the equipment loop. */
734
+ let weapon: GameObject | null = null;
735
+ let launcher: GameObject | null = null;
736
+
737
+ /* Reset (1896) and set various defaults (1898-1900). */
738
+ const state: PlayerState = {
739
+ statAdd: new Array<number>(STAT_MAX).fill(0),
740
+ statInd: new Array<number>(STAT_MAX).fill(0),
741
+ statUse: new Array<number>(STAT_MAX).fill(0),
742
+ statTop: new Array<number>(STAT_MAX).fill(0),
743
+ skills: new Array<number>(SKILL_MAX).fill(0),
744
+ speed: 110,
745
+ numBlows: 100,
746
+ numShots: 0,
747
+ numMoves: 0,
748
+ ammoMult: 0,
749
+ ammoTval: 0,
750
+ ac: 0,
751
+ damRed: 0,
752
+ percDamRed: 0,
753
+ toA: 0,
754
+ toH: 0,
755
+ toD: 0,
756
+ seeInfra: 0,
757
+ curLight: 0,
758
+ heavyWield: false,
759
+ heavyShoot: false,
760
+ blessWield: false,
761
+ cumberArmor: false,
762
+ flags: new FlagSet(OF_SIZE),
763
+ pflags: new FlagSet(PF_SIZE),
764
+ elInfo: [],
765
+ hold: 0,
766
+ };
767
+
768
+ /* Extract race/class info (1902-1914). */
769
+ state.seeInfra = race.infravision;
770
+ for (let i = 0; i < SKILL_MAX; i++) {
771
+ state.skills[i] = (race.skills[i] ?? 0) + (cls.skills[i] ?? 0);
772
+ }
773
+ const vuln = new Array<boolean>(elemCount).fill(false);
774
+ for (let i = 0; i < elemCount; i++) {
775
+ const raceRes = race.elInfo[i]?.resLevel ?? 0;
776
+ if (raceRes === -1) {
777
+ vuln[i] = true;
778
+ state.elInfo.push({ resLevel: 0 });
779
+ } else {
780
+ state.elInfo.push({ resLevel: raceRes });
781
+ }
782
+ }
783
+
784
+ /* Base pflags (1916-1919). */
785
+ state.pflags.wipe();
786
+ state.pflags.copy(race.pflags);
787
+ state.pflags.union(cls.pflags);
788
+
789
+ /* Extract the player flags (1921-1922; player.c:290-300). */
790
+ const collectF = playerFlags(player);
791
+
792
+ /* Analyze equipment (1924-2025). Equipped objects arrive from the caller
793
+ (options.equipment, indexed by body slot). Each item's pval MODIFIERS are
794
+ gated by the player's learned-rune mask (p->obj_k->modifiers): upstream
795
+ multiplies every modifier by obj_k, so a bonus is inert until its rune is
796
+ known, and runes are UNKNOWN by default (PORT_PLAN.md decision 25) -- at
797
+ birth, item modifiers contribute nothing until learned. The el_info and
798
+ combat bonuses (to_a/to_h/to_d) are NOT rune-gated for the real state
799
+ (upstream gates those only for the displayed known_state), so they apply
800
+ unconditionally here.
801
+
802
+ Per-object curse traversal (2009-2023) IS ported: the inner while walks
803
+ from the worn item to each of its active curse objects, folding each
804
+ one's own template object (modifiers/flags/toH/toD/toA/elInfo) into the
805
+ state through the SAME loop body (applySource), in the exact upstream
806
+ accumulation order (worn item first, then its curses in ascending index
807
+ order). The curse template objects come from the bound registry
808
+ (options.curses == upstream's global curses[]); a curse object carries no
809
+ ac and no tval, matching the zeroed fields of the upstream curse struct
810
+ (curse ac is a guaranteed no-op, tval 0 makes tval_is_digger false).
811
+ Still DEFERRED (parity ledger): the learn-by-use rune system that
812
+ populates obj_k (obj-knowledge.c), pending its own increment. */
813
+ const equipment = options.equipment ?? [];
814
+ const curseTable = options.curses ?? [];
815
+ const knownMods = player.objKnown.modifiers;
816
+
817
+ /* The single loop body upstream applies to the worn item AND to each of its
818
+ curse objects (the do/while at 1930-2024). A worn GameObject satisfies
819
+ BonusSource directly; a curse template is adapted with ac 0 / tval 0 (the
820
+ upstream curse struct leaves those zero). Kept as one closure so the two
821
+ never diverge -- this is calc_bonuses' one loop body, not a fork. */
822
+ interface BonusSource {
823
+ flags: FlagSet;
824
+ modifiers: number[];
825
+ elInfo: readonly ElementInfo[];
826
+ ac: number;
827
+ toA: number;
828
+ toH: number;
829
+ toD: number;
830
+ tval: number;
831
+ }
832
+ const applySource = (
833
+ src: BonusSource,
834
+ isWeaponSlot: boolean,
835
+ isBowSlot: boolean,
836
+ ): void => {
837
+ /* Extract the item flags (1933-1939). */
838
+ collectF.union(src.flags);
839
+
840
+ /* Apply modifiers (1941-1981), each multiplied by the learned-rune mask
841
+ (obj->modifiers[X] * p->obj_k->modifiers[X]). The five stat modifiers
842
+ share indices with STAT_* (OBJ_MOD_STR == STAT_STR == 0). */
843
+ for (let s = 0; s < STAT_MAX; s++) {
844
+ state.statAdd[s] =
845
+ (state.statAdd[s] ?? 0) + (src.modifiers[s] ?? 0) * (knownMods[s] ?? 0);
846
+ }
847
+ state.skills[SKILL.STEALTH] =
848
+ (state.skills[SKILL.STEALTH] ?? 0) +
849
+ (src.modifiers[OBJ_MOD.STEALTH] ?? 0) * (knownMods[OBJ_MOD.STEALTH] ?? 0);
850
+ state.skills[SKILL.SEARCH] =
851
+ (state.skills[SKILL.SEARCH] ?? 0) +
852
+ (src.modifiers[OBJ_MOD.SEARCH] ?? 0) * 5 * (knownMods[OBJ_MOD.SEARCH] ?? 0);
853
+ state.seeInfra +=
854
+ (src.modifiers[OBJ_MOD.INFRA] ?? 0) * (knownMods[OBJ_MOD.INFRA] ?? 0);
855
+
856
+ let dig = 0;
857
+ if (tvalIsDigger(src.tval)) {
858
+ if (src.flags.has(OF.DIG_1)) dig = 1;
859
+ else if (src.flags.has(OF.DIG_2)) dig = 2;
860
+ else if (src.flags.has(OF.DIG_3)) dig = 3;
861
+ }
862
+ dig += (src.modifiers[OBJ_MOD.TUNNEL] ?? 0) * (knownMods[OBJ_MOD.TUNNEL] ?? 0);
863
+ state.skills[SKILL.DIGGING] = (state.skills[SKILL.DIGGING] ?? 0) + dig * 20;
864
+
865
+ state.speed +=
866
+ (src.modifiers[OBJ_MOD.SPEED] ?? 0) * (knownMods[OBJ_MOD.SPEED] ?? 0);
867
+ state.damRed +=
868
+ (src.modifiers[OBJ_MOD.DAM_RED] ?? 0) * (knownMods[OBJ_MOD.DAM_RED] ?? 0);
869
+ extraBlows += (src.modifiers[OBJ_MOD.BLOWS] ?? 0) * (knownMods[OBJ_MOD.BLOWS] ?? 0);
870
+ extraShots += (src.modifiers[OBJ_MOD.SHOTS] ?? 0) * (knownMods[OBJ_MOD.SHOTS] ?? 0);
871
+ extraMight += (src.modifiers[OBJ_MOD.MIGHT] ?? 0) * (knownMods[OBJ_MOD.MIGHT] ?? 0);
872
+ extraMoves += (src.modifiers[OBJ_MOD.MOVES] ?? 0) * (knownMods[OBJ_MOD.MOVES] ?? 0);
873
+
874
+ /* Apply element info, noting vulnerabilities for later (1983-1993). */
875
+ for (let jj = 0; jj < elemCount; jj++) {
876
+ const oel = src.elInfo[jj];
877
+ const sel = state.elInfo[jj] as PlayerElementInfo;
878
+ if (!oel) continue;
879
+ if (oel.resLevel === -1) vuln[jj] = true;
880
+ if (oel.resLevel > sel.resLevel) sel.resLevel = oel.resLevel;
881
+ }
882
+
883
+ /* Apply combat bonuses (1995-2007). The wielded weapon's and launcher's
884
+ own to_h/to_d are applied at attack time, not here. A curse object's ac
885
+ is 0 (curse struct carries none). */
886
+ state.ac += src.ac;
887
+ state.toA += src.toA;
888
+ if (!isWeaponSlot && !isBowSlot) {
889
+ state.toH += src.toH;
890
+ state.toD += src.toD;
891
+ }
892
+ };
893
+
894
+ for (let i = 0; i < player.body.count; i++) {
895
+ const worn = equipment[i] ?? null;
896
+ if (!worn) continue;
897
+
898
+ const slotType = player.body.slots[i]?.type;
899
+ const isWeaponSlot = slotType === "WEAPON";
900
+ const isBowSlot = slotType === "BOW";
901
+ /* weapon/launcher are the WORN items (upstream reads them by slot name
902
+ before the loop, 1885-1886); a curse object never becomes the weapon. */
903
+ if (isWeaponSlot) weapon = worn;
904
+ if (isBowSlot) launcher = worn;
905
+
906
+ /* curse := obj->curses, the worn item's curse_data array, held fixed while
907
+ we walk the item and its curse objects (1928, 2009-2023). */
908
+ const curse = worn.curses;
909
+ let obj: BonusSource | null = worn;
910
+ let index = 0;
911
+ while (obj) {
912
+ applySource(obj, isWeaponSlot, isBowSlot);
913
+
914
+ /* Move to any unprocessed curse object (2009-2023). Scan the worn item's
915
+ curse_data for the next active (power != 0) curse, resolving its
916
+ template object from the bound registry (curses[index].obj). The scan
917
+ bound is z_info->curse_max == curseTable.length. */
918
+ if (curse) {
919
+ index++;
920
+ obj = null;
921
+ while (index < curseTable.length) {
922
+ if (curse[index]?.power) {
923
+ const template = curseTable[index]?.obj;
924
+ obj = template
925
+ ? {
926
+ flags: template.flags,
927
+ modifiers: template.modifiers,
928
+ elInfo: template.elInfo,
929
+ ac: 0,
930
+ toA: template.toA,
931
+ toH: template.toH,
932
+ toD: template.toD,
933
+ tval: 0,
934
+ }
935
+ : null;
936
+ break;
937
+ } else {
938
+ index++;
939
+ }
940
+ }
941
+ } else {
942
+ obj = null;
943
+ }
944
+ }
945
+ }
946
+
947
+ /* Apply the collected flags (2027-2028). */
948
+ state.flags.union(collectF);
949
+
950
+ /* Add shapechange info (calc_shapechange, 1798/2030): a non-normal
951
+ shape's combat bonuses, skills, flags and modifiers stack on top of
952
+ the equipment, and its resists apply when better (vulnerabilities
953
+ join the vuln pass below). The normal shape is null (all zeros). */
954
+ const shape = player.shape;
955
+ if (shape) {
956
+ state.toA += shape.toA;
957
+ state.toH += shape.toH;
958
+ state.toD += shape.toD;
959
+ for (let i = 0; i < SKILL_MAX; i++) {
960
+ state.skills[i] = (state.skills[i] ?? 0) + (shape.skills[i] ?? 0);
961
+ }
962
+ state.flags.union(shape.flags);
963
+ state.pflags.union(shape.pflags);
964
+ for (let s = 0; s < STAT_MAX; s++) {
965
+ state.statAdd[s] = (state.statAdd[s] ?? 0) + (shape.modifiers[s] ?? 0);
966
+ }
967
+ state.skills[SKILL.STEALTH] =
968
+ (state.skills[SKILL.STEALTH] ?? 0) +
969
+ (shape.modifiers[OBJ_MOD.STEALTH] ?? 0);
970
+ state.skills[SKILL.SEARCH] =
971
+ (state.skills[SKILL.SEARCH] ?? 0) +
972
+ (shape.modifiers[OBJ_MOD.SEARCH] ?? 0) * 5;
973
+ state.seeInfra += shape.modifiers[OBJ_MOD.INFRA] ?? 0;
974
+ state.skills[SKILL.DIGGING] =
975
+ (state.skills[SKILL.DIGGING] ?? 0) +
976
+ (shape.modifiers[OBJ_MOD.TUNNEL] ?? 0) * 20;
977
+ state.speed += shape.modifiers[OBJ_MOD.SPEED] ?? 0;
978
+ state.damRed += shape.modifiers[OBJ_MOD.DAM_RED] ?? 0;
979
+ extraBlows += shape.modifiers[OBJ_MOD.BLOWS] ?? 0;
980
+ extraShots += shape.modifiers[OBJ_MOD.SHOTS] ?? 0;
981
+ extraMight += shape.modifiers[OBJ_MOD.MIGHT] ?? 0;
982
+ extraMoves += shape.modifiers[OBJ_MOD.MOVES] ?? 0;
983
+
984
+ /* Resists and vulnerabilities. */
985
+ for (let i = 0; i < elemCount; i++) {
986
+ const sel = state.elInfo[i] as PlayerElementInfo;
987
+ const res = shape.elInfo[i]?.resLevel ?? 0;
988
+ if (res === -1) vuln[i] = true;
989
+ else if (res > sel.resLevel) sel.resLevel = res;
990
+ }
991
+ }
992
+
993
+ /* Now deal with vulnerabilities (2034-2038). */
994
+ for (let i = 0; i < elemCount; i++) {
995
+ const el = state.elInfo[i] as PlayerElementInfo;
996
+ if (vuln[i] && el.resLevel < 3) el.resLevel--;
997
+ }
998
+
999
+ /* Calculate light (2040-2041). */
1000
+ calcLight(player, state, options);
1001
+
1002
+ /* Unlight (2043-2046). */
1003
+ const characterDungeon = options.characterDungeon ?? false;
1004
+ if (state.pflags.has(PF.UNLIGHT) && characterDungeon) {
1005
+ const el = state.elInfo[ELEM.DARK];
1006
+ if (el) el.resLevel = 1;
1007
+ }
1008
+
1009
+ /* Evil (2048-2052). */
1010
+ if (state.pflags.has(PF.EVIL) && characterDungeon) {
1011
+ const nether = state.elInfo[ELEM.NETHER];
1012
+ if (nether) nether.resLevel = 1;
1013
+ const holy = state.elInfo[ELEM.HOLY_ORB];
1014
+ if (holy) holy.resLevel = -1;
1015
+ }
1016
+
1017
+ /* Calculate the various stat values (2054-2092). */
1018
+ for (let i = 0; i < STAT_MAX; i++) {
1019
+ let add = state.statAdd[i] ?? 0;
1020
+ add += (race.statAdj[i] ?? 0) + (cls.statAdj[i] ?? 0);
1021
+ state.statTop[i] = modifyStatValue(player.statMax[i] ?? 0, add);
1022
+ const use = modifyStatValue(player.statCur[i] ?? 0, add);
1023
+ state.statUse[i] = use;
1024
+ let ind = statUseToIndex(use);
1025
+ /* The !update hypothetical-blows index shift (2077-2088): applied only
1026
+ when a caller supplies statIndBoost (obj-info's hypothetical re-derive);
1027
+ the live refresh path leaves it undefined and takes the update=true
1028
+ branch (no shift). */
1029
+ const boost = options.statIndBoost;
1030
+ if (boost) {
1031
+ if (i === STAT.STR) ind = Math.max(3, Math.min(37, ind + boost.str));
1032
+ else if (i === STAT.DEX) ind = Math.max(3, Math.min(37, ind + boost.dex));
1033
+ }
1034
+ state.statInd[i] = ind;
1035
+ }
1036
+
1037
+ /* The timed model (FOOD 2094-2132 + the timed block 2134-2213) is gated on
1038
+ the bound table being supplied. An empty table disables BOTH halves -- the
1039
+ table-driven grade / flag / temp_resist logic AND the per-timer combat
1040
+ branches -- so a caller that omits the table gets a consistent "no timed
1041
+ effects" derive rather than a partial one (see CalcBonusesOptions). */
1042
+ const timedEffects = options.timedEffects ?? [];
1043
+ const update = options.update ?? true;
1044
+ if (timedEffects.length > 0) {
1045
+ /* Effects of food outside the "Fed" range (2094-2132). PY_FOOD_* are the
1046
+ FOOD grade maxes (player-timed.c:320-338), already FOOD_VALUE-scaled in
1047
+ the bound table: Fed.max = PY_FOOD_FULL, Full.max = PY_FOOD_MAX,
1048
+ Hungry.max = PY_FOOD_HUNGRY. */
1049
+ const foodEffect = timedEffects[TMD.FOOD];
1050
+ if (foodEffect && !playerTimedGradeEq(player, foodEffect, "Fed")) {
1051
+ const foodMax = (name: string): number =>
1052
+ foodEffect.grades.find((g) => g.name === name)?.max ?? 0;
1053
+ const pyFoodFull = foodMax("Fed");
1054
+ const pyFoodMax = foodMax("Full");
1055
+ const pyFoodHungry = foodMax("Hungry");
1056
+ const food = player.timed[TMD.FOOD] ?? 0;
1057
+ const excess = food - pyFoodFull;
1058
+ const lack = pyFoodHungry - food;
1059
+ if (excess > 0 && !player.timed[TMD.ATT_VAMP]) {
1060
+ /* Scale to units 1/10 of the range and subtract from speed. */
1061
+ state.speed -= Math.trunc((excess * 10) / (pyFoodMax - pyFoodFull));
1062
+ } else if (lack > 0) {
1063
+ /* Scale to units 1/20 of the range. */
1064
+ const l = Math.trunc((lack * 20) / pyFoodHungry);
1065
+ state.toH -= l;
1066
+ state.toD -= l;
1067
+ if (l > 10 && l <= 15) {
1068
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1069
+ state.skills[SKILL.DEVICE] ?? 0, -1, 10, 0);
1070
+ } else if (l > 15 && l <= 18) {
1071
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1072
+ state.skills[SKILL.DEVICE] ?? 0, -1, 5, 0);
1073
+ state.skills[SKILL.DISARM_PHYS] =
1074
+ Math.trunc(((state.skills[SKILL.DISARM_PHYS] ?? 0) * 9) / 10);
1075
+ state.skills[SKILL.DISARM_MAGIC] =
1076
+ Math.trunc(((state.skills[SKILL.DISARM_MAGIC] ?? 0) * 9) / 10);
1077
+ } else if (l > 18) {
1078
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1079
+ state.skills[SKILL.DEVICE] ?? 0, -3, 10, 0);
1080
+ state.skills[SKILL.DISARM_PHYS] =
1081
+ Math.trunc(((state.skills[SKILL.DISARM_PHYS] ?? 0) * 8) / 10);
1082
+ state.skills[SKILL.DISARM_MAGIC] =
1083
+ Math.trunc(((state.skills[SKILL.DISARM_MAGIC] ?? 0) * 8) / 10);
1084
+ state.skills[SKILL.SAVE] =
1085
+ Math.trunc(((state.skills[SKILL.SAVE] ?? 0) * 9) / 10);
1086
+ state.skills[SKILL.SEARCH] =
1087
+ Math.trunc(((state.skills[SKILL.SEARCH] ?? 0) * 9) / 10);
1088
+ }
1089
+ }
1090
+ }
1091
+
1092
+ /* Other timed effects (2134-2213). */
1093
+ /* player_flags_timed (2135; player.c:310-320): OR each active effect's
1094
+ oflag_dup into state.flags, except TMD_TRAPSAFE (excluded so the
1095
+ OF_TRAP_IMMUNE learning hack can tell timed from innate). */
1096
+ for (let i = 0; i < TMD_MAX; i++) {
1097
+ const eff = timedEffects[i];
1098
+ if (
1099
+ player.timed[i] &&
1100
+ eff &&
1101
+ eff.oflagDup !== 0 &&
1102
+ i !== TMD.TRAPSAFE
1103
+ ) {
1104
+ state.flags.on(eff.oflagDup);
1105
+ }
1106
+ }
1107
+
1108
+ /* STUN grade (2137-2151): the FASTCAST-zeroing is the one faithful
1109
+ player.timed mutation this derive makes, gated on `update`. */
1110
+ const stunEffect = timedEffects[TMD.STUN];
1111
+ if (stunEffect && playerTimedGradeEq(player, stunEffect, "Heavy Stun")) {
1112
+ state.toH -= 20;
1113
+ state.toD -= 20;
1114
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1115
+ state.skills[SKILL.DEVICE] ?? 0, -1, 5, 0);
1116
+ if (update) player.timed[TMD.FASTCAST] = 0;
1117
+ } else if (stunEffect && playerTimedGradeEq(player, stunEffect, "Stun")) {
1118
+ state.toH -= 5;
1119
+ state.toD -= 5;
1120
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1121
+ state.skills[SKILL.DEVICE] ?? 0, -1, 10, 0);
1122
+ if (update) player.timed[TMD.FASTCAST] = 0;
1123
+ }
1124
+ if (player.timed[TMD.INVULN]) {
1125
+ state.toA += 100;
1126
+ }
1127
+ if (player.timed[TMD.BLESSED]) {
1128
+ state.toA += 5;
1129
+ state.toH += 10;
1130
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1131
+ state.skills[SKILL.DEVICE] ?? 0, 1, 20, 0);
1132
+ }
1133
+ if (player.timed[TMD.SHIELD]) {
1134
+ state.toA += 50;
1135
+ }
1136
+ if (player.timed[TMD.STONESKIN]) {
1137
+ state.toA += 40;
1138
+ state.speed -= 5;
1139
+ }
1140
+ if (player.timed[TMD.HERO]) {
1141
+ state.toH += 12;
1142
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1143
+ state.skills[SKILL.DEVICE] ?? 0, 1, 20, 0);
1144
+ }
1145
+ if (player.timed[TMD.SHERO]) {
1146
+ state.skills[SKILL.TO_HIT_MELEE] =
1147
+ (state.skills[SKILL.TO_HIT_MELEE] ?? 0) + 75;
1148
+ state.toA -= 10;
1149
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1150
+ state.skills[SKILL.DEVICE] ?? 0, -1, 10, 0);
1151
+ }
1152
+ if (player.timed[TMD.FAST] || player.timed[TMD.SPRINT]) {
1153
+ state.speed += 10;
1154
+ }
1155
+ if (player.timed[TMD.SLOW]) {
1156
+ state.speed -= 10;
1157
+ }
1158
+ if (player.timed[TMD.SINFRA]) {
1159
+ state.seeInfra += 5;
1160
+ }
1161
+ if (player.timed[TMD.TERROR]) {
1162
+ state.speed += 10;
1163
+ }
1164
+ /* Temporary elemental resists (2188-2194): each active temp_resist effect
1165
+ bumps its element's res_level by one, capped at 2 through this path. */
1166
+ for (let i = 0; i < TMD_MAX; i++) {
1167
+ const eff = timedEffects[i];
1168
+ if (!player.timed[i] || !eff || eff.tempResist === -1) continue;
1169
+ const el = state.elInfo[eff.tempResist];
1170
+ if (el && el.resLevel < 2) el.resLevel++;
1171
+ }
1172
+ if (player.timed[TMD.CONFUSED]) {
1173
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1174
+ state.skills[SKILL.DEVICE] ?? 0, -1, 4, 0);
1175
+ }
1176
+ if (player.timed[TMD.AMNESIA]) {
1177
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1178
+ state.skills[SKILL.DEVICE] ?? 0, -1, 5, 0);
1179
+ }
1180
+ if (player.timed[TMD.POISONED]) {
1181
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1182
+ state.skills[SKILL.DEVICE] ?? 0, -1, 20, 0);
1183
+ }
1184
+ if (player.timed[TMD.IMAGE]) {
1185
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1186
+ state.skills[SKILL.DEVICE] ?? 0, -1, 5, 0);
1187
+ }
1188
+ if (player.timed[TMD.BLOODLUST]) {
1189
+ const bl = player.timed[TMD.BLOODLUST] ?? 0;
1190
+ state.toD += Math.trunc(bl / 2);
1191
+ extraBlows += Math.trunc(bl / 20);
1192
+ }
1193
+ if (player.timed[TMD.STEALTH]) {
1194
+ state.skills[SKILL.STEALTH] = (state.skills[SKILL.STEALTH] ?? 0) + 10;
1195
+ }
1196
+ }
1197
+
1198
+ /* Analyze flags - check for fear (2215-2220). Innate flags can in
1199
+ principle carry OF_AFRAID (mods), so the check is ported. */
1200
+ if (state.flags.has(OF.AFRAID)) {
1201
+ state.toH -= 20;
1202
+ state.toA += 8;
1203
+ state.skills[SKILL.DEVICE] = adjustSkillScale(
1204
+ state.skills[SKILL.DEVICE] ?? 0,
1205
+ -1,
1206
+ 20,
1207
+ 0,
1208
+ );
1209
+ }
1210
+
1211
+ /* Analyze weight (2222-2230). */
1212
+ const j = player.upkeep.totalWeight;
1213
+ const limit = weightLimit(state);
1214
+ if (j > Math.trunc(limit / 2)) {
1215
+ state.speed -=
1216
+ Math.trunc((j - Math.trunc(limit / 2)) / Math.trunc(limit / 10));
1217
+ }
1218
+ if (state.speed < 0) state.speed = 0;
1219
+ if (state.speed > 199) state.speed = 199;
1220
+
1221
+ /* Apply modifier bonuses (2232-2236). */
1222
+ state.toA += at(adj_dex_ta, state.statInd[STAT.DEX] ?? 0);
1223
+ state.toD += at(adj_str_td, state.statInd[STAT.STR] ?? 0);
1224
+ state.toH += at(adj_dex_th, state.statInd[STAT.DEX] ?? 0);
1225
+ state.toH += at(adj_str_th, state.statInd[STAT.STR] ?? 0);
1226
+
1227
+ /* Modify skills (2239-2250). */
1228
+ applySkillStatAndLevel(state.skills, cls, player.lev, state.statInd);
1229
+ state.hold = at(adj_str_hold, state.statInd[STAT.STR] ?? 0);
1230
+
1231
+ /* Analyze launcher (2254-2288). object_weight_one is per-item weight; a
1232
+ wielded launcher has number 1. */
1233
+ state.heavyShoot = false;
1234
+ if (launcher) {
1235
+ const launcherWeight = launcher.weight;
1236
+ if (state.hold < Math.trunc(launcherWeight / 10)) {
1237
+ state.toH += 2 * (state.hold - Math.trunc(launcherWeight / 10));
1238
+ state.heavyShoot = true;
1239
+ }
1240
+ state.numShots = 10;
1241
+ if (launcher.kind.kindFlags.has(KF.SHOOTS_SHOTS)) state.ammoTval = TV.SHOT;
1242
+ else if (launcher.kind.kindFlags.has(KF.SHOOTS_ARROWS)) state.ammoTval = TV.ARROW;
1243
+ else if (launcher.kind.kindFlags.has(KF.SHOOTS_BOLTS)) state.ammoTval = TV.BOLT;
1244
+ state.ammoMult = launcher.pval;
1245
+ if (!state.heavyShoot) {
1246
+ state.numShots += extraShots;
1247
+ state.ammoMult += extraMight;
1248
+ if (state.pflags.has(PF.FAST_SHOT)) {
1249
+ state.numShots += Math.trunc(player.lev / 3);
1250
+ }
1251
+ }
1252
+ if (state.numShots < 10) state.numShots = 10;
1253
+ }
1254
+
1255
+ /* Analyze weapon (2291-2319). An empty weapon slot uses the unarmed branch
1256
+ (2316-2319); a too-heavy weapon keeps num_blows at its 1-blow default. */
1257
+ state.heavyWield = false;
1258
+ state.blessWield = false;
1259
+ if (weapon) {
1260
+ const weaponWeight = weapon.weight;
1261
+ if (state.hold < Math.trunc(weaponWeight / 10)) {
1262
+ state.toH += 2 * (state.hold - Math.trunc(weaponWeight / 10));
1263
+ state.heavyWield = true;
1264
+ }
1265
+ if (!state.heavyWield) {
1266
+ state.numBlows = calcBlows(
1267
+ cls,
1268
+ weaponWeight,
1269
+ state.statInd[STAT.STR] ?? 0,
1270
+ state.statInd[STAT.DEX] ?? 0,
1271
+ extraBlows,
1272
+ );
1273
+ state.skills[SKILL.DIGGING] =
1274
+ (state.skills[SKILL.DIGGING] ?? 0) + Math.trunc(weaponWeight / 10);
1275
+ }
1276
+ if (
1277
+ state.pflags.has(PF.BLESS_WEAPON) &&
1278
+ (weapon.tval === TV.HAFTED || state.flags.has(OF.BLESSED))
1279
+ ) {
1280
+ state.toD += 2;
1281
+ state.blessWield = true;
1282
+ }
1283
+ } else {
1284
+ /* Unarmed (2316-2319). */
1285
+ state.numBlows = calcBlows(
1286
+ cls,
1287
+ null,
1288
+ state.statInd[STAT.STR] ?? 0,
1289
+ state.statInd[STAT.DEX] ?? 0,
1290
+ extraBlows,
1291
+ );
1292
+ }
1293
+
1294
+ /* Mana (2321-2325): calc_mana DEFERRED. The PF_NO_MANA check reads
1295
+ p->msp, which is 0 until calc_mana is ported (correct for warriors;
1296
+ see the ledger for the caster caveat). */
1297
+ if (!player.msp) {
1298
+ state.pflags.on(PF.NO_MANA);
1299
+ }
1300
+
1301
+ /* Movement speed (2327-2328): num_moves = extra_moves. */
1302
+ state.numMoves = extraMoves;
1303
+
1304
+ return state;
1305
+ }
1306
+
1307
+ /* ------------------------------------------------------------------ */
1308
+ /* Inventory ordering (earlier_object) */
1309
+ /* ------------------------------------------------------------------ */
1310
+
1311
+ /**
1312
+ * The hooks earlier_object reads off the globals it can't see in isolation:
1313
+ * player->state.ammo_tval (usable-ammo preference), object_value(obj, 1),
1314
+ * object_flavor_is_aware(obj) and obj_can_browse(obj). Each defaults to the
1315
+ * value that makes its branch a no-op (ammoTval 0, value 0, aware, not a
1316
+ * browsable book), so a caller comparing ammo only needs ammoTval + objectValue.
1317
+ */
1318
+ export interface EarlierObjectOpts {
1319
+ /** `store` argument (skips the book / flavor / light branches). */
1320
+ store?: boolean;
1321
+ /** player->state.ammo_tval: the currently-usable ammo tval. */
1322
+ ammoTval?: number;
1323
+ /** object_value(obj, 1): the per-item price used for the value tiebreak. */
1324
+ objectValue?: (obj: GameObject) => number;
1325
+ /** object_flavor_is_aware(obj): defaults to aware (true). */
1326
+ isAware?: (obj: GameObject) => boolean;
1327
+ /** obj_can_browse(obj): a readable spellbook. Defaults to false. */
1328
+ canBrowse?: (obj: GameObject) => boolean;
1329
+ }
1330
+
1331
+ /**
1332
+ * earlier_object (player-calcs.c:934-1003): decide whether `next` should
1333
+ * replace `orig` as the object that comes earlier in the standard inventory
1334
+ * listing (returns true to replace). Ported statement-for-statement; the
1335
+ * globals earlier_object reads (player->state.ammo_tval, object_value,
1336
+ * object_flavor_is_aware, obj_can_browse) arrive through EarlierObjectOpts.
1337
+ * `pval` (light fuel) is read straight off the object.
1338
+ */
1339
+ export function earlierObject(
1340
+ orig: GameObject | null,
1341
+ next: GameObject | null,
1342
+ opts: EarlierObjectOpts = {},
1343
+ ): boolean {
1344
+ /* Check we have actual objects (938-940). */
1345
+ if (!next) return false;
1346
+ if (!orig) return true;
1347
+
1348
+ const store = opts.store ?? false;
1349
+ const ammoTval = opts.ammoTval ?? 0;
1350
+ const value = opts.objectValue ?? (() => 0);
1351
+ const aware = opts.isAware ?? (() => true);
1352
+ const canBrowse = opts.canBrowse ?? (() => false);
1353
+
1354
+ if (!store) {
1355
+ /* Readable books always come first (943-945). */
1356
+ if (canBrowse(orig) && !canBrowse(next)) return false;
1357
+ if (!canBrowse(orig) && canBrowse(next)) return true;
1358
+ }
1359
+
1360
+ /* Usable ammo is before other ammo (948-956). */
1361
+ if (tvalIsAmmo(orig.tval) && tvalIsAmmo(next.tval)) {
1362
+ if (ammoTval === orig.tval && ammoTval !== next.tval) return false;
1363
+ if (ammoTval !== orig.tval && ammoTval === next.tval) return true;
1364
+ }
1365
+
1366
+ /* Objects sort by decreasing type (959-961). */
1367
+ if (orig.tval > next.tval) return false;
1368
+ if (orig.tval < next.tval) return true;
1369
+
1370
+ if (!store) {
1371
+ /* Non-aware (flavored) items always come last (966-969). */
1372
+ if (!aware(next)) return false;
1373
+ if (!aware(orig)) return true;
1374
+ }
1375
+
1376
+ /* Objects sort by increasing sval (972-974). */
1377
+ if (orig.sval < next.sval) return false;
1378
+ if (orig.sval > next.sval) return true;
1379
+
1380
+ if (!store) {
1381
+ /* Unaware objects always come last (977-979). The port marks a kind as
1382
+ * flavored by tval (tvalCanHaveFlavor), the same convention obj/value.ts and
1383
+ * obj/desc.ts use, since bound ObjectKind carries no flavor pointer. */
1384
+ if (tvalCanHaveFlavor(next.tval) && !aware(next)) return false;
1385
+ if (tvalCanHaveFlavor(orig.tval) && !aware(orig)) return true;
1386
+
1387
+ /* Lights sort by decreasing fuel (982-985). */
1388
+ if (tvalIsLight(orig.tval)) {
1389
+ if (orig.pval > next.pval) return false;
1390
+ if (orig.pval < next.pval) return true;
1391
+ }
1392
+ }
1393
+
1394
+ /* Objects sort by decreasing value, except ammo which sorts increasing
1395
+ * (988-999). */
1396
+ if (tvalIsAmmo(orig.tval)) {
1397
+ if (value(orig) < value(next)) return false;
1398
+ if (value(orig) > value(next)) return true;
1399
+ } else {
1400
+ if (value(orig) > value(next)) return false;
1401
+ if (value(orig) < value(next)) return true;
1402
+ }
1403
+
1404
+ /* No preference (1002). */
1405
+ return false;
1406
+ }
1407
+
1408
+ /* ------------------------------------------------------------------ */
1409
+ /* Adapters for the combat and turn-loop consumers */
1410
+ /* ------------------------------------------------------------------ */
1411
+
1412
+ /**
1413
+ * The player_state fields player-attack.c reads as p->state, shaped as
1414
+ * combat/melee.ts PlayerCombatState. The skills array is shared, not
1415
+ * copied: recompute the state rather than mutating it.
1416
+ */
1417
+ export function toCombatState(state: PlayerState): PlayerCombatState {
1418
+ return {
1419
+ toH: state.toH,
1420
+ toD: state.toD,
1421
+ ac: state.ac,
1422
+ toA: state.toA,
1423
+ skills: state.skills,
1424
+ numBlows: state.numBlows,
1425
+ ammoMult: state.ammoMult,
1426
+ numShots: state.numShots,
1427
+ ammoTval: state.ammoTval,
1428
+ blessWield: state.blessWield,
1429
+ };
1430
+ }
1431
+
1432
+ /**
1433
+ * The player_state fields mon-attack.c reads (p->state.ac + p->state.to_a),
1434
+ * shaped as combat/mon-melee.ts DefenderState.
1435
+ */
1436
+ export function toDefenderState(state: PlayerState): DefenderState {
1437
+ return { ac: state.ac, toA: state.toA };
1438
+ }
1439
+
1440
+ /**
1441
+ * What the encumbrance notices need to know about the gear, beyond the two
1442
+ * states: upstream asks equipped_item_by_slot_name(p, ...) to tell "you put the
1443
+ * heavy thing down" apart from "you swapped it for a manageable one".
1444
+ */
1445
+ export interface BonusChangeGear {
1446
+ /** equipped_item_by_slot_name(p, "shooting") != NULL. */
1447
+ hasLauncher: boolean;
1448
+ /** equipped_item_by_slot_name(p, "weapon") != NULL. */
1449
+ hasWeapon: boolean;
1450
+ }
1451
+
1452
+ /**
1453
+ * calc_bonuses' state-change notices (player-calcs.c:2412-2453): the messages
1454
+ * upstream emits when heavy_shoot / heavy_wield / bless_wield / cumber_armor
1455
+ * flip between the OLD p->state and the NEWLY derived state, in upstream's
1456
+ * order. Returns the lines to emit, so the diff stays pure and testable and the
1457
+ * session layer owns the message sink.
1458
+ *
1459
+ * calcBonuses itself cannot do this: it is a pure derive that never sees the
1460
+ * previous state (upstream reads p->state, messages, and only then memcpy's the
1461
+ * new one over it). That is why every one of these ten messages was missing -
1462
+ * the derive was ported and the diff at the end of the same function was not, so
1463
+ * wielding a weapon far too heavy for your STR said nothing at all.
1464
+ *
1465
+ * Upstream gates the whole block on !p->upkeep->only_partial. The port has no
1466
+ * partial-update mode - the hypothetical derives (best-digger, item inspection)
1467
+ * pass update:false and simply never reach this - so there is no flag to test.
1468
+ */
1469
+ export function bonusChangeMessages(
1470
+ prev: PlayerState,
1471
+ next: PlayerState,
1472
+ gear: BonusChangeGear,
1473
+ ): string[] {
1474
+ const out: string[] = [];
1475
+
1476
+ /* "heavy bow" (2413-2422). */
1477
+ if (prev.heavyShoot !== next.heavyShoot) {
1478
+ if (next.heavyShoot) {
1479
+ out.push("You have trouble wielding such a heavy bow.");
1480
+ } else if (gear.hasLauncher) {
1481
+ out.push("You have no trouble wielding your bow.");
1482
+ } else {
1483
+ out.push("You feel relieved to put down your heavy bow.");
1484
+ }
1485
+ }
1486
+
1487
+ /* "heavy weapon" (2424-2433). */
1488
+ if (prev.heavyWield !== next.heavyWield) {
1489
+ if (next.heavyWield) {
1490
+ out.push("You have trouble wielding such a heavy weapon.");
1491
+ } else if (gear.hasWeapon) {
1492
+ out.push("You have no trouble wielding your weapon.");
1493
+ } else {
1494
+ out.push("You feel relieved to put down your heavy weapon.");
1495
+ }
1496
+ }
1497
+
1498
+ /* "illegal weapon" - a priest wielding an unblessed edged weapon
1499
+ * (2435-2443). Note the asymmetry: upstream emits nothing when the offending
1500
+ * weapon is simply removed, so there is no third branch here. */
1501
+ if (prev.blessWield !== next.blessWield) {
1502
+ if (next.blessWield) {
1503
+ out.push("You feel attuned to your weapon.");
1504
+ } else if (gear.hasWeapon) {
1505
+ out.push("You feel less attuned to your weapon.");
1506
+ }
1507
+ }
1508
+
1509
+ /* "armor state" (2445-2452). */
1510
+ if (prev.cumberArmor !== next.cumberArmor) {
1511
+ out.push(
1512
+ next.cumberArmor
1513
+ ? "The weight of your armor reduces your maximum SP."
1514
+ : "Your maximum SP is no longer reduced by armor weight.",
1515
+ );
1516
+ }
1517
+
1518
+ return out;
1519
+ }
1520
+
1521
+ /** Re-export for callers computing HP arrays over all levels. */
1522
+ export { PY_MAX_LEVEL };