@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,1737 @@
1
+ /**
2
+ * Object inspection, ported from reference/src/obj-info.c (Angband 4.2.6):
3
+ * object_info_out (L2315) and its describe_* helpers, obj_known_blows (L864),
4
+ * obj_known_damage / o_obj_known_damage (L1023 / L1264), obj_known_digging
5
+ * (L1813), obj_known_light (L1914), obj_known_effect / describe_effect
6
+ * (L2013 / L2060), describe_combat (L1752), describe_origin (L2177) and
7
+ * describe_flavor_text (L2252).
8
+ *
9
+ * The engine is a PURE READ: it reproduces upstream's block order, separators,
10
+ * wording, punctuation, colours (COLOUR_* -> color.ts) and integer math, and
11
+ * MUST NOT draw from the game RNG. Every value comes from deterministic reads
12
+ * or randcalc(timeout, MINIMISE/MAXIMISE) fixed bounds; calcBonuses /
13
+ * calcBlows / calcDiggingChances / breakageChance are deterministic given
14
+ * state, and the hypothetical-wield re-derive is driven through a deps closure
15
+ * that must pass update=false and never roll. See object-info.test.ts for the
16
+ * RNG-invariance guard.
17
+ *
18
+ * The result is a Textblock: an ordered list of coloured runs with literal
19
+ * '\n' in the text (the faithful analogue of z-textblock's textblock_append /
20
+ * textblock_append_c). Word-wrapping to a display width is a presentation
21
+ * concern left to the shell (packages/web wrapRuns), so the core emits logical
22
+ * lines only, exactly as the character-dump path needs.
23
+ *
24
+ * Game-layer data the upstream reads from globals (the player, the rune env,
25
+ * the projection table, the monster-race registry, the built effect chain, the
26
+ * constants and options) is injected via ObjectInfoDeps rather than reached
27
+ * from a live GameState, so the engine is reusable by inspect, the store look
28
+ * command and object recall without a second divergent copy.
29
+ */
30
+
31
+ import {
32
+ COLOUR_GREEN,
33
+ COLOUR_L_GREEN,
34
+ COLOUR_L_RED,
35
+ COLOUR_L_WHITE,
36
+ COLOUR_RED,
37
+ COLOUR_WHITE,
38
+ COLOUR_YELLOW,
39
+ } from "../color.js";
40
+ import { OF, OBJ_MOD } from "../generated/index.js";
41
+ import { ORIGIN, ORIGIN_ENTRIES } from "../generated/origins.js";
42
+ import {
43
+ MELEE_CRIT,
44
+ MELEE_CRIT_LEVELS,
45
+ RANGED_CRIT,
46
+ RANGED_CRIT_LEVELS,
47
+ type CriticalLevel,
48
+ } from "../combat/hit.js";
49
+ import { chanceOfMeleeHitBase } from "../combat/melee.js";
50
+ import { chanceOfMissileHitBase } from "../combat/ranged.js";
51
+ import type { PlayerCombatState } from "../combat/melee.js";
52
+ import type { PlayerState } from "../player/calcs.js";
53
+ import type { Player } from "../player/player.js";
54
+ import { SKILL, STAT_MAX } from "../player/types.js";
55
+ import type { MyRational } from "../rational.js";
56
+ import {
57
+ myRationalConstruct,
58
+ myRationalProduct,
59
+ myRationalSum,
60
+ myRationalToUint,
61
+ } from "../rational.js";
62
+ import type { RandomValue } from "../rng.js";
63
+ import type { ProjectionInfo } from "../world/projection.js";
64
+ import type { RuneEnv } from "./knowledge.js";
65
+ import { OBJ_NOTICE, objectHasStandardToH, sustainFlag } from "./knowledge.js";
66
+ import type { KnownDesc } from "./known-object.js";
67
+ import {
68
+ objectEffectIsKnown,
69
+ objectFullyKnown,
70
+ objectKnownShadow,
71
+ } from "./known-object.js";
72
+ import type { CurseData, GameObject } from "./object.js";
73
+ import {
74
+ copyBrands,
75
+ copySlays,
76
+ objectWeightOne,
77
+ tvalIsAmmo,
78
+ tvalIsEdible,
79
+ tvalIsFuel,
80
+ tvalIsLight,
81
+ tvalIsMeleeWeapon,
82
+ tvalIsPotion,
83
+ tvalIsRod,
84
+ tvalIsScroll,
85
+ tvalIsStaff,
86
+ tvalIsUseable,
87
+ tvalIsWand,
88
+ tvalIsWeapon,
89
+ tvalIsWearable,
90
+ } from "./object.js";
91
+ import {
92
+ EL_INFO_HATES,
93
+ EL_INFO_IGNORE,
94
+ ELEM_MAX,
95
+ OBJ_MOD_MAX,
96
+ OBJ_PROPERTY,
97
+ OFT,
98
+ type ObjectProperty,
99
+ } from "./types.js";
100
+
101
+ /* ------------------------------------------------------------------ *
102
+ * OINFO modes (obj-info.h L28-35). Values MUST match upstream so the
103
+ * EGO / FAKE / TERSE / SPOIL gates in describe_stats / get_known_flags /
104
+ * get_known_elements stay correct when the character dump, store look and
105
+ * ego-recall reuse the engine.
106
+ * ------------------------------------------------------------------ */
107
+ export const OINFO = {
108
+ NONE: 0x00,
109
+ TERSE: 0x01,
110
+ SUBJ: 0x02,
111
+ EGO: 0x04,
112
+ FAKE: 0x08,
113
+ SPOIL: 0x10,
114
+ } as const;
115
+
116
+ /* ------------------------------------------------------------------ *
117
+ * Textblock (z-textblock analogue).
118
+ * ------------------------------------------------------------------ */
119
+
120
+ /** One coloured run of text; '\n' stays literal inside `text`. */
121
+ export interface TextRun {
122
+ text: string;
123
+ /** COLOUR_* attr (color.ts). */
124
+ attr: number;
125
+ }
126
+
127
+ /** The run-stream object_info returns. */
128
+ export interface Textblock {
129
+ runs: TextRun[];
130
+ }
131
+
132
+ /** textblock_new (z-textblock.c L57): an empty run stream. */
133
+ export function tbNew(): Textblock {
134
+ return { runs: [] };
135
+ }
136
+
137
+ /**
138
+ * textblock_append (z-textblock.c L166): default (white) colour.
139
+ *
140
+ * Upstream is variadic and vformats; the port's callers interpolate first, so
141
+ * this takes the finished string. Empty appends are dropped rather than pushing
142
+ * a zero-length run, which is invisible to textblockToString and to
143
+ * textblockAttrs alike (the C's vstrnfmt of "" also writes nothing).
144
+ */
145
+ export function tbAppend(tb: Textblock, text: string): void {
146
+ if (text.length > 0) tb.runs.push({ text, attr: COLOUR_WHITE });
147
+ }
148
+
149
+ /** textblock_append_c (z-textblock.c L179): coloured. */
150
+ export function tbAppendC(tb: Textblock, attr: number, text: string): void {
151
+ if (text.length > 0) tb.runs.push({ text, attr });
152
+ }
153
+
154
+ /**
155
+ * textblock_append_textblock (z-textblock.c L153): append every character AND
156
+ * its attribute from `tba` onto `tb`, leaving `tba` UNTOUCHED so the caller can
157
+ * keep using or free it independently (upstream's callers at obj-info.c L2135,
158
+ * effects-info.c L262/L296/L367, ui-equip-cmp.c L1457/L1462 and
159
+ * ui-knowledge.c L3052 all free the source afterwards, which is only safe
160
+ * because this copies).
161
+ *
162
+ * The runs are copied rather than aliased for the same reason: a later append to
163
+ * `tb` must not be able to reach into `tba`'s run objects.
164
+ */
165
+ export function tbAppendTextblock(tb: Textblock, tba: Textblock): void {
166
+ for (const r of tba.runs) tb.runs.push({ text: r.text, attr: r.attr });
167
+ }
168
+
169
+ /**
170
+ * textblock_attrs (z-textblock.c L201): the PER-CHARACTER attribute array.
171
+ *
172
+ * The port stores runs, not parallel character arrays, because that is what its
173
+ * front ends consume; this is the flattening upstream's display_area
174
+ * (ui-output.c L145) reads, and it is the shape upstream's own tests assert
175
+ * against. attrs[i] is the colour of textblockToString(tb)[i].
176
+ */
177
+ export function textblockAttrs(tb: Textblock): number[] {
178
+ const attrs: number[] = [];
179
+ for (const r of tb.runs) {
180
+ for (let i = 0; i < r.text.length; i++) attrs.push(r.attr);
181
+ }
182
+ return attrs;
183
+ }
184
+
185
+ /** Concatenate the entire run-stream text (tests / plain readouts). */
186
+ export function textblockToString(tb: Textblock): string {
187
+ let s = "";
188
+ for (const r of tb.runs) s += r.text;
189
+ return s;
190
+ }
191
+
192
+ /* ------------------------------------------------------------------ *
193
+ * Dependency bag.
194
+ * ------------------------------------------------------------------ */
195
+
196
+ /** o-*-critical constants (z_info) for the O-combat damage path. */
197
+ export interface OCritConstants {
198
+ powerTohScaleNumerator?: number;
199
+ powerTohScaleDenominator?: number;
200
+ powerLaunchedTohScaleNumerator?: number;
201
+ powerLaunchedTohScaleDenominator?: number;
202
+ powerThrownTohScaleNumerator?: number;
203
+ powerThrownTohScaleDenominator?: number;
204
+ chancePowerScaleNumerator: number;
205
+ chancePowerScaleDenominator: number;
206
+ chanceAddDenominator: number;
207
+ levels: readonly { chance: number; dice: number; msg: string }[];
208
+ }
209
+
210
+ /** z_info scalars the engine reads. */
211
+ export interface ObjectInfoConstants {
212
+ fuelLamp: number;
213
+ maxRange: number;
214
+ oMeleeCritical: OCritConstants;
215
+ oRangedCritical: OCritConstants;
216
+ }
217
+
218
+ /**
219
+ * The effect-description seam. The bridge builds the object_effect(obj) chain
220
+ * (obj-cmd.ts buildObjectEffectChain over obj.activation?.effect ?? obj.effect)
221
+ * and provides a describeEffect closure with the projection table baked in, so
222
+ * the core stays free of the effects-interpreter and the game layer.
223
+ */
224
+ export interface ObjectInfoEffectDeps {
225
+ /**
226
+ * effect_describe(effect, prefix, boost, false): the "When used, it ..."
227
+ * sentence, or null when the chain has nothing to say. Returns plain text
228
+ * (the port's effect-info dropped digit-colouring).
229
+ */
230
+ describe(prefix: string | null, boost: number, onlyFirst: boolean): string | null;
231
+ /** effect_aim(object_effect(obj)): the effect requires a target. */
232
+ aimed: boolean;
233
+ /** get_use_device_chance(obj) out of 1000; used only for zappers/rods. */
234
+ deviceFailure: number;
235
+ }
236
+
237
+ /** A resolved monster-race origin (describe_origin). */
238
+ export interface OriginRace {
239
+ name: string;
240
+ unique: boolean;
241
+ comma: boolean;
242
+ }
243
+
244
+ /** Everything object_info_out reads that a live GameState cannot supply pure. */
245
+ export interface ObjectInfoDeps {
246
+ player: Player;
247
+ env: RuneEnv;
248
+ known: KnownDesc;
249
+ /** Full ProjectionInfo[] indexed by PROJ value (element names etc). */
250
+ projections: readonly ProjectionInfo[];
251
+ z: ObjectInfoConstants;
252
+ /** OPT(player, birth_percent_damage). */
253
+ percentDamage: boolean;
254
+ /** OPT(player, birth_randarts). */
255
+ randarts: boolean;
256
+ /** The player's real derived state (player->state): ammo, missile crits, speed. */
257
+ currentState: PlayerState;
258
+ /** turn_energy(player->state.speed), for the recharge line. */
259
+ speedMultiplier: number;
260
+ /** The player's current equipped objects, indexed by body slot (null = empty). */
261
+ equipObjects: readonly (GameObject | null)[];
262
+ /** equipped_item_by_slot_name(player, "shooting"): the launcher, or null. */
263
+ bow: GameObject | null;
264
+ /** slot_by_name(player, "weapon"): the body-slot index of the weapon. */
265
+ weaponSlot: number;
266
+ /** wield_slot(obj): the body-slot the object would occupy (digging). */
267
+ wieldSlot(obj: GameObject): number;
268
+ /**
269
+ * Hypothetical calc_bonuses: calcBonuses(player, { equipment, update: false,
270
+ * statIndBoost: { str, dex }, ...liveOptions }). The clone with the inspected
271
+ * object placed in a slot is built by the engine; the closure only derives.
272
+ */
273
+ deriveState(
274
+ equip: readonly (GameObject | null)[],
275
+ strBoost: number,
276
+ dexBoost: number,
277
+ ): PlayerState;
278
+ /** Resolve GameObject.originRace (a handle) to a race name + flags, or null. */
279
+ raceOrigin?(handle: number): OriginRace | null;
280
+ /** breakage_chance(obj, true) (combat/ranged.ts). */
281
+ breakageChance(obj: GameObject): number;
282
+ /** calc_digging_chances(skill) (game/cave-cmd.ts): chances out of 1600. */
283
+ calcDiggingChances(diggingSkill: number): number[];
284
+ /** obj_can_browse(obj): a book the player's class can read. Defaults false. */
285
+ canBrowse?(obj: GameObject): boolean;
286
+ /** The object_effect(obj) description seam. */
287
+ effect: ObjectInfoEffectDeps;
288
+ /** object_is_in_store(obj): inspect from a store. Defaults false. */
289
+ inStore?: boolean;
290
+ }
291
+
292
+ /* ------------------------------------------------------------------ *
293
+ * Small helpers.
294
+ * ------------------------------------------------------------------ */
295
+
296
+ /** randcalc(v, 0, MINIMISE). */
297
+ function rvMin(v: RandomValue): number {
298
+ return v.base + v.dice;
299
+ }
300
+ /** randcalc(v, 0, MAXIMISE). */
301
+ function rvMax(v: RandomValue): number {
302
+ return v.base + v.dice * v.sides + v.mBonus;
303
+ }
304
+
305
+ /** is_a_vowel (z-util.c). */
306
+ function isAVowel(c: string): boolean {
307
+ return "aeiouAEIOU".includes(c);
308
+ }
309
+
310
+ /** C "%+i" (always-signed integer). */
311
+ function plusI(n: number): string {
312
+ return n < 0 ? String(n) : `+${n}`;
313
+ }
314
+
315
+ /** Substitute %s placeholders left to right. */
316
+ function sprintfS(fmt: string, ...args: string[]): string {
317
+ let i = 0;
318
+ return fmt.replace(/%s/g, () => args[i++] ?? "");
319
+ }
320
+
321
+ function lookupProp(
322
+ env: RuneEnv,
323
+ type: number,
324
+ propIndex: number,
325
+ ): ObjectProperty | null {
326
+ for (const p of env.properties) {
327
+ if (p && p.type === type && p.propIndex === propIndex) return p;
328
+ }
329
+ return null;
330
+ }
331
+
332
+ /** object_to_hit(obj->known) (obj-util.c L296): shadow to-hit plus curses. */
333
+ function objToHit(o: GameObject, env: RuneEnv): number {
334
+ let result = o.toH;
335
+ if (o.curses) {
336
+ for (let i = 1; i < env.curses.length; i++) {
337
+ if (o.curses[i]?.power) result += env.curses[i]?.obj.toH ?? 0;
338
+ }
339
+ }
340
+ return result;
341
+ }
342
+ /** object_to_dam(obj->known). */
343
+ function objToDam(o: GameObject, env: RuneEnv): number {
344
+ let result = o.toD;
345
+ if (o.curses) {
346
+ for (let i = 1; i < env.curses.length; i++) {
347
+ if (o.curses[i]?.power) result += env.curses[i]?.obj.toD ?? 0;
348
+ }
349
+ }
350
+ return result;
351
+ }
352
+
353
+ /** info_out_list (obj-info.c L78): "a, b, c.\n". */
354
+ function infoOutList(tb: Textblock, list: string[]): void {
355
+ for (let i = 0; i < list.length; i++) {
356
+ tbAppend(tb, list[i] as string);
357
+ if (i !== list.length - 1) tbAppend(tb, ", ");
358
+ }
359
+ tbAppend(tb, ".\n");
360
+ }
361
+
362
+ /* ------------------------------------------------------------------ *
363
+ * Element info view (get_known_elements, obj-info.c L814).
364
+ * ------------------------------------------------------------------ */
365
+
366
+ interface ElView {
367
+ resLevel: number;
368
+ flags: number;
369
+ }
370
+
371
+ function getKnownElements(
372
+ obj: GameObject,
373
+ shadow: GameObject,
374
+ p: Player,
375
+ mode: number,
376
+ ): ElView[] {
377
+ const out: ElView[] = [];
378
+ for (let i = 0; i < ELEM_MAX; i++) {
379
+ const known = p.objKnown.elInfo[i]?.resLevel ?? 0;
380
+ let resLevel = 0;
381
+ if (known || mode & OINFO.SPOIL) {
382
+ resLevel = shadow.elInfo[i]?.resLevel ?? 0;
383
+ }
384
+ let flags = shadow.elInfo[i]?.flags ?? 0;
385
+ /* Ignoring an element. */
386
+ if ((obj.elInfo[i]?.flags ?? 0) & EL_INFO_IGNORE) {
387
+ if ((obj.elInfo[i]?.flags ?? 0) & EL_INFO_HATES) {
388
+ flags &= ~EL_INFO_HATES;
389
+ } else {
390
+ flags &= ~EL_INFO_IGNORE;
391
+ }
392
+ }
393
+ if (mode & OINFO.TERSE) flags &= ~EL_INFO_HATES;
394
+ out.push({ resLevel, flags });
395
+ }
396
+ return out;
397
+ }
398
+
399
+ /* ------------------------------------------------------------------ *
400
+ * describe_* helpers (obj-info.c).
401
+ * ------------------------------------------------------------------ */
402
+
403
+ function describeCurses(tb: Textblock, shadow: GameObject, env: RuneEnv): boolean {
404
+ const c = shadow.curses;
405
+ if (!c) return false;
406
+ for (let i = 1; i < env.curses.length; i++) {
407
+ if (c[i]?.power) {
408
+ tbAppend(tb, "It ");
409
+ tbAppendC(tb, COLOUR_L_RED, env.curses[i]?.desc ?? "");
410
+ if (c[i]?.power === 100) tbAppend(tb, "; this curse cannot be removed");
411
+ tbAppend(tb, ".\n");
412
+ }
413
+ }
414
+ return true;
415
+ }
416
+
417
+ function describeStats(
418
+ tb: Textblock,
419
+ shadow: GameObject,
420
+ env: RuneEnv,
421
+ mode: number,
422
+ aware: boolean,
423
+ ): boolean {
424
+ const suppressDetails = (mode & (OINFO.EGO | OINFO.FAKE)) !== 0;
425
+ let knownEffect = false;
426
+ if (shadow.ego) knownEffect = true;
427
+ /* tval_can_have_flavor_k && object_flavor_is_aware (jewellery). */
428
+ if (aware) knownEffect = true;
429
+
430
+ let count = 0;
431
+ for (let i = 0; i < OBJ_MOD_MAX; i++) {
432
+ if (shadow.modifiers[i]) count++;
433
+ }
434
+ const detail = count > 0;
435
+ if (!count) return false;
436
+
437
+ for (let i = 0; i < OBJ_MOD_MAX; i++) {
438
+ const val = shadow.modifiers[i] ?? 0;
439
+ if (!val) continue;
440
+ const desc =
441
+ lookupProp(env, OBJ_PROPERTY.MOD, i)?.name ??
442
+ lookupProp(env, OBJ_PROPERTY.STAT, i)?.name ??
443
+ "";
444
+ if (detail && !suppressDetails) {
445
+ const attr = val > 0 ? COLOUR_L_GREEN : COLOUR_RED;
446
+ tbAppendC(tb, attr, `${plusI(val)} ${desc}.\n`);
447
+ } else if (knownEffect) {
448
+ tbAppend(tb, `Affects your ${desc}.\n`);
449
+ }
450
+ }
451
+ return true;
452
+ }
453
+
454
+ function describeSlays(tb: Textblock, shadow: GameObject, env: RuneEnv): boolean {
455
+ const s = shadow.slays;
456
+ if (!s) return false;
457
+ if (tvalIsWeapon(shadow.tval) || tvalIsFuel(shadow.tval)) {
458
+ tbAppend(tb, "Slays ");
459
+ } else {
460
+ tbAppend(tb, "It causes your melee attacks to slay ");
461
+ }
462
+ let count = 0;
463
+ for (let i = 1; i < env.slays.length; i++) if (s[i]) count++;
464
+ for (let i = 1; i < env.slays.length; i++) {
465
+ if (!s[i]) continue;
466
+ tbAppend(tb, env.slays[i]?.name ?? "");
467
+ if ((env.slays[i]?.multiplier ?? 0) > 3) tbAppend(tb, " (powerfully)");
468
+ if (count > 1) tbAppend(tb, ", ");
469
+ else tbAppend(tb, ".\n");
470
+ count--;
471
+ }
472
+ return true;
473
+ }
474
+
475
+ function describeBrands(tb: Textblock, shadow: GameObject, env: RuneEnv): boolean {
476
+ const b = shadow.brands;
477
+ if (!b) return false;
478
+ if (tvalIsWeapon(shadow.tval) || tvalIsFuel(shadow.tval)) {
479
+ tbAppend(tb, "Branded with ");
480
+ } else {
481
+ tbAppend(tb, "It brands your melee attacks with ");
482
+ }
483
+ let count = 0;
484
+ for (let i = 1; i < env.brands.length; i++) if (b[i]) count++;
485
+ for (let i = 1; i < env.brands.length; i++) {
486
+ if (!b[i]) continue;
487
+ if ((env.brands[i]?.multiplier ?? 0) < 3) tbAppend(tb, "weak ");
488
+ tbAppend(tb, env.brands[i]?.name ?? "");
489
+ if (count > 1) tbAppend(tb, ", ");
490
+ else tbAppend(tb, ".\n");
491
+ count--;
492
+ }
493
+ return true;
494
+ }
495
+
496
+ function describeElements(
497
+ tb: Textblock,
498
+ el: ElView[],
499
+ projections: readonly ProjectionInfo[],
500
+ ): boolean {
501
+ let prev = false;
502
+ const collect = (test: (r: number) => boolean): string[] => {
503
+ const out: string[] = [];
504
+ for (let i = 0; i < ELEM_MAX; i++) {
505
+ if (test(el[i]?.resLevel ?? 0)) out.push(projections[i]?.name ?? "");
506
+ }
507
+ return out;
508
+ };
509
+ const imm = collect((r) => r === 3);
510
+ if (imm.length) {
511
+ tbAppend(tb, "Provides immunity to ");
512
+ infoOutList(tb, imm);
513
+ prev = true;
514
+ }
515
+ const res = collect((r) => r === 1);
516
+ if (res.length) {
517
+ tbAppend(tb, "Provides resistance to ");
518
+ infoOutList(tb, res);
519
+ prev = true;
520
+ }
521
+ const vul = collect((r) => r === -1);
522
+ if (vul.length) {
523
+ tbAppend(tb, "Makes you vulnerable to ");
524
+ infoOutList(tb, vul);
525
+ prev = true;
526
+ }
527
+ return prev;
528
+ }
529
+
530
+ function describeProtects(tb: Textblock, flags: GameObject["flags"], env: RuneEnv): boolean {
531
+ const descs: string[] = [];
532
+ for (let i = 1; i < OF.MAX; i++) {
533
+ const prop = lookupProp(env, OBJ_PROPERTY.FLAG, i);
534
+ if (!prop || prop.subtype !== OFT.PROT) continue;
535
+ if (flags.has(i)) descs.push(prop.desc);
536
+ }
537
+ if (!descs.length) return false;
538
+ tbAppend(tb, "Provides protection from ");
539
+ infoOutList(tb, descs);
540
+ return true;
541
+ }
542
+
543
+ function describeIgnores(
544
+ tb: Textblock,
545
+ el: ElView[],
546
+ projections: readonly ProjectionInfo[],
547
+ ): boolean {
548
+ const descs: string[] = [];
549
+ for (let i = 0; i < ELEM_MAX; i++) {
550
+ if ((el[i]?.flags ?? 0) & EL_INFO_IGNORE) descs.push(projections[i]?.name ?? "");
551
+ }
552
+ if (!descs.length) return false;
553
+ tbAppend(tb, "Cannot be harmed by ");
554
+ infoOutList(tb, descs);
555
+ return true;
556
+ }
557
+
558
+ function describeHates(
559
+ tb: Textblock,
560
+ el: ElView[],
561
+ projections: readonly ProjectionInfo[],
562
+ ): boolean {
563
+ const descs: string[] = [];
564
+ for (let i = 0; i < ELEM_MAX; i++) {
565
+ if ((el[i]?.flags ?? 0) & EL_INFO_HATES) descs.push(projections[i]?.name ?? "");
566
+ }
567
+ if (!descs.length) return false;
568
+ tbAppend(tb, "Can be destroyed by ");
569
+ infoOutList(tb, descs);
570
+ return true;
571
+ }
572
+
573
+ function describeSustains(tb: Textblock, flags: GameObject["flags"], env: RuneEnv): boolean {
574
+ const descs: string[] = [];
575
+ for (let i = 0; i < STAT_MAX; i++) {
576
+ const prop = lookupProp(env, OBJ_PROPERTY.STAT, i);
577
+ if (!prop) continue;
578
+ if (flags.has(sustainFlag(i))) descs.push(prop.name);
579
+ }
580
+ if (!descs.length) return false;
581
+ tbAppend(tb, "Sustains ");
582
+ infoOutList(tb, descs);
583
+ return true;
584
+ }
585
+
586
+ function describeMiscMagic(tb: Textblock, flags: GameObject["flags"], env: RuneEnv): boolean {
587
+ let printed = false;
588
+ for (let i = 1; i < OF.MAX; i++) {
589
+ const prop = lookupProp(env, OBJ_PROPERTY.FLAG, i);
590
+ if (!prop) continue;
591
+ if (prop.subtype !== OFT.MISC && prop.subtype !== OFT.MELEE && prop.subtype !== OFT.BAD) {
592
+ continue;
593
+ }
594
+ if (flags.has(i)) {
595
+ tbAppend(tb, `${prop.desc}. `);
596
+ printed = true;
597
+ }
598
+ }
599
+ if (printed) tbAppend(tb, "\n");
600
+ return printed;
601
+ }
602
+
603
+ /* ------------------------------------------------------------------ *
604
+ * Critical-hit averages (calculate_melee_crits / calculate_missile_crits).
605
+ * ------------------------------------------------------------------ */
606
+
607
+ interface CritScale {
608
+ mult: number;
609
+ add: number;
610
+ div: number;
611
+ multRound: number;
612
+ addRound: number;
613
+ sclRound: number;
614
+ }
615
+
616
+ /** The shared level-band summation of calculate_*_crits (obj-info.c L488-540). */
617
+ function critScale(
618
+ critChance: number,
619
+ weight: number,
620
+ chanceRange: number,
621
+ powerWeightScl: number,
622
+ powerRandom: number,
623
+ levels: readonly CriticalLevel[],
624
+ ): CritScale {
625
+ const div = 100;
626
+ if (critChance > 0 && levels.length > 0) {
627
+ let minPower = powerWeightScl * weight + 1;
628
+ const maxPower = minPower - 1 + powerRandom;
629
+ let multSum = 0;
630
+ let addSum = 0;
631
+ let i = 0;
632
+ const last = levels.length - 1;
633
+ while (minPower <= maxPower) {
634
+ const lvl = levels[i] as CriticalLevel;
635
+ let w: number;
636
+ if (maxPower < lvl.cutoff || i === last) {
637
+ w = maxPower - minPower + 1;
638
+ minPower = maxPower + 1;
639
+ } else {
640
+ if (minPower >= lvl.cutoff) {
641
+ i++;
642
+ continue;
643
+ }
644
+ w = lvl.cutoff - minPower;
645
+ minPower = lvl.cutoff;
646
+ }
647
+ multSum += w * (lvl.mult - 1);
648
+ addSum += w * lvl.add;
649
+ i++;
650
+ }
651
+ const scale = Math.trunc(chanceRange / div) * powerRandom;
652
+ return {
653
+ mult: div + Math.trunc((critChance * multSum) / scale),
654
+ add: Math.trunc((critChance * addSum) / scale),
655
+ multRound: (critChance * multSum) % scale,
656
+ addRound: (critChance * addSum) % scale,
657
+ sclRound: scale,
658
+ div,
659
+ };
660
+ }
661
+ return { mult: 100, add: 0, div, multRound: 0, addRound: 0, sclRound: 1 };
662
+ }
663
+
664
+ function calculateMeleeCrits(
665
+ deps: ObjectInfoDeps,
666
+ state: PlayerState,
667
+ weight: number,
668
+ plus: number,
669
+ ): CritScale {
670
+ let critChance =
671
+ MELEE_CRIT.chanceWeightScl * weight +
672
+ MELEE_CRIT.chanceTohScl * (state.toH + plus) +
673
+ MELEE_CRIT.chanceLevelScl * deps.player.lev +
674
+ MELEE_CRIT.chanceTohSkillScl * (state.skills[SKILL.TO_HIT_MELEE] ?? 0) +
675
+ MELEE_CRIT.chanceOffset;
676
+ critChance = Math.min(MELEE_CRIT.chanceRange, Math.max(0, critChance));
677
+ return critScale(
678
+ critChance,
679
+ weight,
680
+ MELEE_CRIT.chanceRange,
681
+ MELEE_CRIT.powerWeightScl,
682
+ MELEE_CRIT.powerRandom,
683
+ MELEE_CRIT_LEVELS,
684
+ );
685
+ }
686
+
687
+ function calculateMissileCrits(
688
+ deps: ObjectInfoDeps,
689
+ state: PlayerState,
690
+ weight: number,
691
+ plus: number,
692
+ launched: boolean,
693
+ ): CritScale {
694
+ let critChance =
695
+ RANGED_CRIT.chanceWeightScl * weight +
696
+ RANGED_CRIT.chanceTohScl * (state.toH + plus) +
697
+ RANGED_CRIT.chanceLevelScl * deps.player.lev +
698
+ RANGED_CRIT.chanceOffset;
699
+ if (launched) {
700
+ critChance +=
701
+ RANGED_CRIT.chanceLaunchedTohSkillScl *
702
+ (deps.currentState.skills[SKILL.TO_HIT_BOW] ?? 0);
703
+ } else {
704
+ critChance +=
705
+ RANGED_CRIT.chanceThrownTohSkillScl *
706
+ (deps.currentState.skills[SKILL.TO_HIT_THROW] ?? 0);
707
+ }
708
+ critChance = Math.min(RANGED_CRIT.chanceRange, Math.max(0, critChance));
709
+ return critScale(
710
+ critChance,
711
+ weight,
712
+ RANGED_CRIT.chanceRange,
713
+ RANGED_CRIT.powerWeightScl,
714
+ RANGED_CRIT.powerRandom,
715
+ RANGED_CRIT_LEVELS,
716
+ );
717
+ }
718
+
719
+ /* ------------------------------------------------------------------ *
720
+ * my_rational + O-combat crits (obj-info.c L435, L561, L723).
721
+ *
722
+ * The rational helpers themselves now live in ../rational, a faithful port of
723
+ * z-util.c that keeps upstream's UINT_MAX saturation and its approximating
724
+ * overflow fallback. This file previously carried a private copy with only the
725
+ * native-arithmetic path; the two agree on every value obj-info can produce
726
+ * (crit chances and dice counts are far below 2^32), so moving to the shared
727
+ * one changes nothing here while giving player-path.c's and obj-randart.c's
728
+ * uses of the same C functions one implementation instead of three.
729
+ * ------------------------------------------------------------------ */
730
+
731
+ type Rational = MyRational;
732
+
733
+ const ratConstruct = myRationalConstruct;
734
+ const ratProduct = myRationalProduct;
735
+ const ratSum = myRationalSum;
736
+
737
+ /** my_rational_to_uint with the remainder out-parameter as a return field. */
738
+ function ratToUint(a: Rational, scale: number): { value: number; remainder: number } {
739
+ const out = { remainder: 0 };
740
+ const value = myRationalToUint(a, scale, out);
741
+ return { value, remainder: out.remainder };
742
+ }
743
+
744
+ /** sum_o_criticals (obj-info.c L435). */
745
+ function sumOCriticals(levels: readonly { chance: number; dice: number }[]): Rational {
746
+ let remaining = ratConstruct(1, 1);
747
+ let added = ratConstruct(0, 1);
748
+ for (let i = 0; i < levels.length; i++) {
749
+ const lvl = levels[i] as { chance: number; dice: number };
750
+ const hasNext = i < levels.length - 1;
751
+ let levelAdded = ratConstruct(lvl.dice, hasNext ? lvl.chance : 1);
752
+ levelAdded = ratProduct(levelAdded, remaining);
753
+ added = ratSum(added, levelAdded);
754
+ if (hasNext) {
755
+ remaining = ratProduct(remaining, ratConstruct(lvl.chance - 1, lvl.chance));
756
+ }
757
+ }
758
+ return added;
759
+ }
760
+
761
+ interface OCritResult {
762
+ dice: number;
763
+ fracDice: Rational;
764
+ }
765
+
766
+ function oCalcCrits(
767
+ power0: number,
768
+ powerNum: number,
769
+ powerDen: number,
770
+ crit: OCritConstants,
771
+ ): OCritResult {
772
+ if (crit.levels.length === 0) return { dice: 0, fracDice: ratConstruct(0, 1) };
773
+ const maxAdded = sumOCriticals(crit.levels);
774
+ let power = Math.trunc((power0 * powerNum) / powerDen);
775
+ const chanceNum = power * crit.chancePowerScaleNumerator;
776
+ const chanceDen =
777
+ power * crit.chancePowerScaleDenominator + crit.chanceAddDenominator;
778
+ if (chanceDen > 0 && chanceNum > 0) {
779
+ if (chanceNum < chanceDen) {
780
+ let t = ratConstruct(chanceNum, chanceDen);
781
+ t = ratProduct(t, maxAdded);
782
+ const { value, remainder } = ratToUint(t, 100);
783
+ return { dice: value, fracDice: ratConstruct(remainder, t.d) };
784
+ }
785
+ const { value, remainder } = ratToUint(maxAdded, 100);
786
+ return { dice: value, fracDice: ratConstruct(remainder, maxAdded.d) };
787
+ }
788
+ return { dice: 0, fracDice: ratConstruct(0, 1) };
789
+ }
790
+
791
+ /** deadliness_conversion[151] (player-attack.c L231). */
792
+ const DEADLINESS_CONVERSION: readonly number[] = [
793
+ 0, 5, 10, 14, 18, 22, 26, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66,
794
+ 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 104, 107, 109, 112, 114, 117,
795
+ 119, 122, 124, 127, 129, 132, 134, 137, 139, 142, 144, 147, 149, 152, 154,
796
+ 157, 159, 162, 164, 167, 169, 172, 174, 176, 178, 180, 182, 184, 186, 188,
797
+ 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218,
798
+ 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248,
799
+ 250, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
800
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
801
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
802
+ 255, 255, 255, 255, 255, 255, 255, 255, 255,
803
+ ];
804
+
805
+ /** apply_deadliness (player-attack.c L261): scale die_average by deadliness. */
806
+ function applyDeadliness(dieAverage: number, deadliness: number): number {
807
+ let dl = deadliness;
808
+ if (dl > 150) dl = 150;
809
+ if (dl < -150) dl = -150;
810
+ if (dl >= 0) {
811
+ const i = DEADLINESS_CONVERSION[dl] as number;
812
+ return dieAverage * (100 + i);
813
+ }
814
+ const i = DEADLINESS_CONVERSION[Math.abs(dl)] as number;
815
+ if (i >= 100) return 0;
816
+ return dieAverage * (100 - i);
817
+ }
818
+
819
+ /* ------------------------------------------------------------------ *
820
+ * Hypothetical-wield helpers.
821
+ * ------------------------------------------------------------------ */
822
+
823
+ /** Clone the current equipment array with `obj` placed in `slot`. */
824
+ function equipWith(
825
+ deps: ObjectInfoDeps,
826
+ obj: GameObject,
827
+ slot: number,
828
+ ): (GameObject | null)[] {
829
+ const eq = deps.equipObjects.slice();
830
+ if (slot >= 0) eq[slot] = obj;
831
+ return eq;
832
+ }
833
+
834
+ function shadowOf(deps: ObjectInfoDeps, o: GameObject): GameObject {
835
+ return objectKnownShadow(o, deps.player, deps.env, deps.known);
836
+ }
837
+
838
+ /* ------------------------------------------------------------------ *
839
+ * obj_known_blows / describe_blows.
840
+ * ------------------------------------------------------------------ */
841
+
842
+ const STAT_RANGE = 38;
843
+
844
+ interface BlowInfo {
845
+ strPlus: number;
846
+ dexPlus: number;
847
+ centiblows: number;
848
+ }
849
+
850
+ function objKnownBlows(deps: ObjectInfoDeps, obj: GameObject, maxNum: number): BlowInfo[] {
851
+ if (!tvalIsMeleeWeapon(obj.tval)) return [];
852
+ const equip = equipWith(deps, obj, deps.weaponSlot);
853
+ const out: BlowInfo[] = [];
854
+
855
+ /* First entry: the current blows (str/dex boost 0, clamp [3,37]). */
856
+ const base = deps.deriveState(equip, 0, 0);
857
+ out.push({ strPlus: 0, dexPlus: 0, centiblows: base.numBlows });
858
+
859
+ const oldBlows = base.numBlows;
860
+ const dexBound = STAT_RANGE - (base.statInd[1] ?? 0);
861
+ const strBound = STAT_RANGE - (base.statInd[0] ?? 0);
862
+ let strFaster = -1;
863
+ let strDone = -1;
864
+
865
+ for (let dexPlus = 0; dexPlus < dexBound; dexPlus++) {
866
+ for (let strPlus = 0; strPlus < strBound; strPlus++) {
867
+ if (out.length === maxNum) return out;
868
+ const s = deps.deriveState(equip, strPlus, dexPlus);
869
+ const newBlows = s.numBlows;
870
+ if (
871
+ newBlows - (newBlows % 10) > oldBlows - (oldBlows % 10) &&
872
+ (strPlus < strDone || strDone === -1)
873
+ ) {
874
+ out.push({
875
+ strPlus,
876
+ dexPlus,
877
+ centiblows: Math.trunc(newBlows / 10) * 10,
878
+ });
879
+ strDone = strPlus;
880
+ break;
881
+ }
882
+ if (
883
+ newBlows > oldBlows &&
884
+ (strPlus < strFaster || strFaster === -1) &&
885
+ (strPlus < strDone || strDone === -1)
886
+ ) {
887
+ out.push({ strPlus, dexPlus, centiblows: newBlows });
888
+ strFaster = strPlus;
889
+ }
890
+ }
891
+ }
892
+ return out;
893
+ }
894
+
895
+ function describeBlows(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject): boolean {
896
+ const entries = objKnownBlows(deps, obj, STAT_RANGE * 2);
897
+ if (entries.length === 0) return false;
898
+ const first = entries[0] as BlowInfo;
899
+ tbAppendC(
900
+ tb,
901
+ COLOUR_L_GREEN,
902
+ `${Math.trunc(first.centiblows / 100)}.${Math.trunc(first.centiblows / 10) % 10} `,
903
+ );
904
+ tbAppend(tb, `blow${first.centiblows > 100 ? "s" : ""}/round.\n`);
905
+ for (let i = 1; i < entries.length; i++) {
906
+ const e = entries[i] as BlowInfo;
907
+ if (e.centiblows % 10 === 0) {
908
+ tbAppend(
909
+ tb,
910
+ `With +${e.strPlus} STR and +${e.dexPlus} DEX you would get ${Math.trunc(
911
+ e.centiblows / 100,
912
+ )}.${Math.trunc(e.centiblows / 10) % 10} blows\n`,
913
+ );
914
+ } else {
915
+ tbAppend(
916
+ tb,
917
+ `With +${e.strPlus} STR and +${e.dexPlus} DEX you would attack a bit faster\n`,
918
+ );
919
+ }
920
+ }
921
+ return true;
922
+ }
923
+
924
+ /* ------------------------------------------------------------------ *
925
+ * obj_known_damage (standard) and o_obj_known_damage (O-combat).
926
+ * ------------------------------------------------------------------ */
927
+
928
+ interface DamageResult {
929
+ normal: number;
930
+ brand: number[];
931
+ slay: number[];
932
+ nonweapSlay: boolean;
933
+ hasBrandsOrSlays: boolean;
934
+ }
935
+
936
+ function collectTotalBrandsSlays(
937
+ deps: ObjectInfoDeps,
938
+ shadow: GameObject,
939
+ weapon: boolean,
940
+ ammo: boolean,
941
+ bowShadow: GameObject | null,
942
+ ): { brands: boolean[]; slays: boolean[]; nonweapSlay: boolean } {
943
+ const env = deps.env;
944
+ let brands = copyBrands(null, shadow.brands, env.brands) ??
945
+ new Array<boolean>(env.brands.length).fill(false);
946
+ let slays = copySlays(null, shadow.slays, env.slays) ??
947
+ new Array<boolean>(env.slays.length).fill(false);
948
+ if (ammo && bowShadow) {
949
+ brands = copyBrands(brands, bowShadow.brands, env.brands) ?? brands;
950
+ slays = copySlays(slays, bowShadow.slays, env.slays) ?? slays;
951
+ }
952
+ let nonweapSlay = false;
953
+ if (weapon) {
954
+ for (let i = 2; i < deps.player.body.count; i++) {
955
+ const slotObj = env.slotObject(i);
956
+ if (!slotObj) continue;
957
+ const ss = shadowOf(deps, slotObj);
958
+ if (ss.brands || ss.slays) nonweapSlay = true;
959
+ else continue;
960
+ brands = copyBrands(brands, ss.brands, env.brands) ?? brands;
961
+ slays = copySlays(slays, ss.slays, env.slays) ?? slays;
962
+ }
963
+ /* Temporary (timed) brands/slays are DEFERRED with the timed-brand system. */
964
+ }
965
+ return { brands, slays, nonweapSlay };
966
+ }
967
+
968
+ function objKnownDamage(deps: ObjectInfoDeps, obj: GameObject, throwIt: boolean): DamageResult {
969
+ const env = deps.env;
970
+ const shadow = shadowOf(deps, obj);
971
+ const brandDamage = new Array<number>(env.brands.length).fill(0);
972
+ const slayDamage = new Array<number>(env.slays.length).fill(0);
973
+ const bow = deps.bow;
974
+ const weapon = tvalIsMeleeWeapon(obj.tval) && !throwIt;
975
+ const ammo = deps.currentState.ammoTval === obj.tval && !!bow && !throwIt;
976
+ const meleeAdjMult = ammo || throwIt ? 0 : 1;
977
+ let multiplier = 1;
978
+
979
+ const state = weapon
980
+ ? deps.deriveState(equipWith(deps, obj, deps.weaponSlot), 0, 0)
981
+ : deps.deriveState(deps.equipObjects.slice(), 0, 0);
982
+
983
+ const dice = shadow.dd;
984
+ const sides = shadow.ds;
985
+ if (!dice || !sides) {
986
+ return { normal: 0, brand: brandDamage, slay: slayDamage, nonweapSlay: false, hasBrandsOrSlays: false };
987
+ }
988
+ let dam = (sides + 1) * dice * 5;
989
+ const plus = objToHit(shadow, env);
990
+ let xtraPostcrit = 0;
991
+ let xtraPrecrit = 0;
992
+ let crit: CritScale;
993
+ let oldBlows = 0;
994
+ const weight = objectWeightOne(obj, env.curses);
995
+
996
+ if (weapon) {
997
+ xtraPostcrit = state.toD * 10;
998
+ xtraPrecrit += objToDam(shadow, env) * 10;
999
+ crit = calculateMeleeCrits(deps, state, weight, plus);
1000
+ oldBlows = state.numBlows;
1001
+ } else if (ammo) {
1002
+ crit = calculateMissileCrits(deps, deps.currentState, weight, plus, true);
1003
+ dam += objToDam(shadow, env) * 10;
1004
+ if (bow) dam += objToDam(shadowOf(deps, bow), env) * 10;
1005
+ } else {
1006
+ crit = calculateMissileCrits(deps, deps.currentState, weight, plus, false);
1007
+ dam += objToDam(shadow, env) * 10;
1008
+ dam *= 2 + Math.trunc(weight / 12);
1009
+ }
1010
+
1011
+ if (ammo) multiplier = deps.currentState.ammoMult;
1012
+
1013
+ const bowShadow = ammo && bow ? shadowOf(deps, bow) : null;
1014
+ const { brands, slays, nonweapSlay } = collectTotalBrandsSlays(
1015
+ deps, shadow, weapon, ammo, bowShadow,
1016
+ );
1017
+
1018
+ let hasBrandsOrSlays = false;
1019
+ const numShots = deps.currentState.numShots;
1020
+
1021
+ /* The thrown branch rounds differently per site (brand uses '>', slay uses
1022
+ '>=', normal uses '>'), so perHit takes a thrownGe flag. */
1023
+ const critTransform = (base: number): { totalDam: number; round: number } => {
1024
+ const temp0 = base;
1025
+ const temp1 =
1026
+ temp0 * crit.mult +
1027
+ 10 * crit.add +
1028
+ Math.trunc((temp0 * crit.multRound + 10 * crit.addRound) / crit.sclRound);
1029
+ return { totalDam: Math.trunc(temp1 / crit.div) + xtraPostcrit, round: temp1 % crit.div };
1030
+ };
1031
+ const perHit = (totalDam: number, round: number, thrownGe: boolean): number => {
1032
+ if (weapon) {
1033
+ const t = totalDam * oldBlows + Math.trunc((round * oldBlows) / crit.div);
1034
+ return Math.trunc(t / 100) + (t % 100 >= 50 ? 1 : 0);
1035
+ }
1036
+ if (ammo) {
1037
+ const t = totalDam * numShots + Math.trunc((round * numShots) / crit.div);
1038
+ return Math.trunc(t / 10) + (t % 10 >= 5 ? 1 : 0);
1039
+ }
1040
+ const half = Math.trunc((crit.div + 1) / 2);
1041
+ return totalDam + ((thrownGe ? round >= half : round > half) ? 1 : 0);
1042
+ };
1043
+
1044
+ for (let i = 1; i < env.brands.length; i++) {
1045
+ if (!brands[i]) continue;
1046
+ hasBrandsOrSlays = true;
1047
+ const base = dam * (multiplier + (env.brands[i]?.multiplier ?? 0) - meleeAdjMult) + xtraPrecrit;
1048
+ const { totalDam, round } = critTransform(base);
1049
+ brandDamage[i] = perHit(totalDam, round, false); /* brand: '>' */
1050
+ }
1051
+ for (let i = 1; i < env.slays.length; i++) {
1052
+ if (!slays[i]) continue;
1053
+ hasBrandsOrSlays = true;
1054
+ const base = dam * (multiplier + (env.slays[i]?.multiplier ?? 0) - meleeAdjMult) + xtraPrecrit;
1055
+ const { totalDam, round } = critTransform(base);
1056
+ slayDamage[i] = perHit(totalDam, round, true); /* slay: '>=' */
1057
+ }
1058
+ {
1059
+ const base = dam * multiplier + xtraPrecrit;
1060
+ const { totalDam, round } = critTransform(base);
1061
+ const normal = perHit(totalDam, round, false); /* normal: '>' */
1062
+ return { normal, brand: brandDamage, slay: slayDamage, nonweapSlay, hasBrandsOrSlays };
1063
+ }
1064
+ }
1065
+
1066
+ function oObjKnownDamage(deps: ObjectInfoDeps, obj: GameObject, throwIt: boolean): DamageResult {
1067
+ const env = deps.env;
1068
+ const shadow = shadowOf(deps, obj);
1069
+ const brandDamage = new Array<number>(env.brands.length).fill(0);
1070
+ const slayDamage = new Array<number>(env.slays.length).fill(0);
1071
+ const bow = deps.bow;
1072
+ const weapon = tvalIsMeleeWeapon(obj.tval) && !throwIt;
1073
+ const ammo = deps.currentState.ammoTval === obj.tval && !!bow && !throwIt;
1074
+ let multiplier = 1;
1075
+ let deadliness = objToDam(shadow, env);
1076
+
1077
+ const state = weapon
1078
+ ? deps.deriveState(equipWith(deps, obj, deps.weaponSlot), 0, 0)
1079
+ : deps.deriveState(deps.equipObjects.slice(), 0, 0);
1080
+
1081
+ let dice = shadow.dd * 100;
1082
+ const sides = shadow.ds;
1083
+ if (!dice || !sides) {
1084
+ return { normal: 0, brand: brandDamage, slay: slayDamage, nonweapSlay: false, hasBrandsOrSlays: false };
1085
+ }
1086
+ let oldBlows = 0;
1087
+ let fracDice = ratConstruct(0, 1);
1088
+ const weight = objectWeightOne(obj, env.curses);
1089
+
1090
+ if (weapon) {
1091
+ const power = chanceOfMeleeHitBase(toCombat(state), obj);
1092
+ const oc = oCalcCrits(
1093
+ power,
1094
+ deps.z.oMeleeCritical.powerTohScaleNumerator ?? 1,
1095
+ deps.z.oMeleeCritical.powerTohScaleDenominator ?? 1,
1096
+ deps.z.oMeleeCritical,
1097
+ );
1098
+ dice += oc.dice;
1099
+ fracDice = oc.fracDice;
1100
+ oldBlows = state.numBlows;
1101
+ } else if (ammo) {
1102
+ const power = chanceOfMissileHitBase(toCombat(deps.currentState), obj, bow);
1103
+ const oc = oCalcMissile(power, deps, true);
1104
+ dice += oc.dice;
1105
+ fracDice = oc.fracDice;
1106
+ } else {
1107
+ const thrownScl = 2 + Math.trunc(weight / 12);
1108
+ const power = chanceOfMissileHitBase(toCombat(deps.currentState), obj, null);
1109
+ const oc = oCalcMissile(power, deps, false);
1110
+ dice += oc.dice;
1111
+ dice *= thrownScl;
1112
+ const { value, remainder } = ratToUint(oc.fracDice, thrownScl);
1113
+ dice += value;
1114
+ fracDice = ratConstruct(remainder, oc.fracDice.d);
1115
+ }
1116
+
1117
+ if (ammo) multiplier = deps.currentState.ammoMult;
1118
+
1119
+ let dieAverage = 5 * (sides + 1);
1120
+ dieAverage *= multiplier;
1121
+ if (ammo && bow) {
1122
+ deadliness += objToDam(shadowOf(deps, bow), env) + state.toD;
1123
+ } else {
1124
+ deadliness += state.toD;
1125
+ }
1126
+ dieAverage = applyDeadliness(dieAverage, Math.min(deadliness, 150));
1127
+
1128
+ const bowShadow = ammo && bow ? shadowOf(deps, bow) : null;
1129
+ const { brands, slays, nonweapSlay } = collectTotalBrandsSlays(
1130
+ deps, shadow, weapon, ammo, bowShadow,
1131
+ );
1132
+
1133
+ let hasBrandsOrSlays = false;
1134
+ const numShots = deps.currentState.numShots;
1135
+
1136
+ const perMult = (oMult: number): number => {
1137
+ let average = dieAverage * oMult;
1138
+ let round = average % 1000;
1139
+ average = Math.trunc(average / 1000);
1140
+ const u1 = ratToUint(fracDice, average);
1141
+ let temp0 = dice * average + Math.trunc((dice * round) / 1000) + u1.value;
1142
+ const fracTemp = ratConstruct(u1.remainder, fracDice.d);
1143
+ const u2 = ratToUint(fracTemp, 1000);
1144
+ round = ((dice * round) % 1000) + u2.value;
1145
+ if (u2.remainder >= Math.trunc((fracTemp.d + 1) / 2)) round++;
1146
+ const add = oMult - 10;
1147
+ let totalDam: number;
1148
+ if (weapon) {
1149
+ totalDam = oldBlows * temp0 + Math.trunc((oldBlows * round) / 1000);
1150
+ const r = totalDam % 10000;
1151
+ totalDam = Math.trunc(totalDam / 10000);
1152
+ totalDam += Math.trunc((add * oldBlows) / 10) + (r >= 5000 ? 1 : 0);
1153
+ } else if (ammo) {
1154
+ totalDam = numShots * temp0 + Math.trunc((numShots * round) / 1000);
1155
+ const r = totalDam % 1000;
1156
+ totalDam = Math.trunc(totalDam / 1000);
1157
+ totalDam += add * numShots + (r >= 500 ? 1 : 0);
1158
+ } else {
1159
+ totalDam = Math.trunc(temp0 / 100) + add * 10 + (temp0 % 100 >= 50 ? 1 : 0);
1160
+ }
1161
+ return totalDam;
1162
+ };
1163
+
1164
+ for (let i = 1; i < env.brands.length; i++) {
1165
+ if (!brands[i]) continue;
1166
+ hasBrandsOrSlays = true;
1167
+ brandDamage[i] = perMult(env.brands[i]?.oMultiplier ?? 0);
1168
+ }
1169
+ for (let i = 1; i < env.slays.length; i++) {
1170
+ if (!slays[i]) continue;
1171
+ hasBrandsOrSlays = true;
1172
+ slayDamage[i] = perMult(env.slays[i]?.oMultiplier ?? 0);
1173
+ }
1174
+
1175
+ /* Normal damage. */
1176
+ const u = ratToUint(fracDice, dieAverage);
1177
+ let temp0 = dice * dieAverage + u.value;
1178
+ if (u.remainder >= Math.trunc((fracDice.d + 1) / 2)) temp0++;
1179
+ let round = temp0 % 1000;
1180
+ temp0 = Math.trunc(temp0 / 1000);
1181
+ let normal: number;
1182
+ if (weapon) {
1183
+ normal = oldBlows * temp0 + Math.trunc((oldBlows * round) / 1000);
1184
+ round = normal % 1000;
1185
+ normal = Math.trunc(normal / 1000);
1186
+ normal += round >= 500 ? 1 : 0;
1187
+ } else if (ammo) {
1188
+ normal = numShots * temp0 + Math.trunc((numShots * round) / 1000);
1189
+ round = normal % 100;
1190
+ normal = Math.trunc(normal / 100);
1191
+ normal += round >= 50 ? 1 : 0;
1192
+ } else {
1193
+ normal = Math.trunc(temp0 / 10) + (temp0 % 10 >= 5 ? 1 : 0);
1194
+ }
1195
+
1196
+ return { normal, brand: brandDamage, slay: slayDamage, nonweapSlay, hasBrandsOrSlays };
1197
+ }
1198
+
1199
+ function oCalcMissile(power: number, deps: ObjectInfoDeps, launched: boolean): OCritResult {
1200
+ const c = deps.z.oRangedCritical;
1201
+ const num = launched
1202
+ ? c.powerLaunchedTohScaleNumerator ?? 1
1203
+ : c.powerThrownTohScaleNumerator ?? 1;
1204
+ const den = launched
1205
+ ? c.powerLaunchedTohScaleDenominator ?? 1
1206
+ : c.powerThrownTohScaleDenominator ?? 1;
1207
+ return oCalcCrits(power, num, den, c);
1208
+ }
1209
+
1210
+ function toCombat(state: PlayerState): PlayerCombatState {
1211
+ return {
1212
+ toH: state.toH,
1213
+ toD: state.toD,
1214
+ ac: state.ac,
1215
+ toA: state.toA,
1216
+ skills: state.skills,
1217
+ numBlows: state.numBlows,
1218
+ ammoMult: state.ammoMult,
1219
+ numShots: state.numShots,
1220
+ ammoTval: state.ammoTval,
1221
+ blessWield: state.blessWield,
1222
+ };
1223
+ }
1224
+
1225
+ /* ------------------------------------------------------------------ *
1226
+ * describe_damage (obj-info.c L1519): sorted, grouped average damage.
1227
+ * ------------------------------------------------------------------ */
1228
+
1229
+ function describeDamage(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject, throwIt: boolean): boolean {
1230
+ const env = deps.env;
1231
+ const res = deps.percentDamage
1232
+ ? oObjKnownDamage(deps, obj, throwIt)
1233
+ : objKnownDamage(deps, obj, throwIt);
1234
+ let hasBrandsOrSlays = res.hasBrandsOrSlays;
1235
+
1236
+ if (res.nonweapSlay) {
1237
+ tbAppend(tb, "This weapon may benefit from one or more off-weapon brands or slays.\n");
1238
+ }
1239
+ tbAppend(tb, throwIt ? "Average thrown damage: " : "Average damage/round: ");
1240
+
1241
+ if (hasBrandsOrSlays) {
1242
+ const brandMax = env.brands.length;
1243
+ const slayMax = env.slays.length;
1244
+ const sortind: number[] = [];
1245
+ for (let i = 0; i < slayMax; i++) {
1246
+ if ((res.slay[i] ?? 0) > 0) sortind.push(i + brandMax);
1247
+ }
1248
+ for (let i = 0; i < brandMax; i++) {
1249
+ if ((res.brand[i] ?? 0) > 0) sortind.push(i);
1250
+ }
1251
+ const damOf = (ind: number): number =>
1252
+ ind < brandMax ? (res.brand[ind] ?? 0) : (res.slay[ind - brandMax] ?? 0);
1253
+ /* Insertion sort, descending. */
1254
+ for (let i = 0; i < sortind.length - 1; i++) {
1255
+ let maxdam = damOf(sortind[i] as number);
1256
+ let maxind = i;
1257
+ for (let j = i + 1; j < sortind.length; j++) {
1258
+ const d = damOf(sortind[j] as number);
1259
+ if (maxdam < d) {
1260
+ maxdam = d;
1261
+ maxind = j;
1262
+ }
1263
+ }
1264
+ if (maxind !== i) {
1265
+ const tmp = sortind[maxind] as number;
1266
+ sortind[maxind] = sortind[i] as number;
1267
+ sortind[i] = tmp;
1268
+ }
1269
+ }
1270
+
1271
+ let lastdam = 0;
1272
+ let groupn = 0;
1273
+ let lastnm: string | null = null;
1274
+ let lastIsBrand = false;
1275
+ for (let i = 0; i < sortind.length; i++) {
1276
+ const ind = sortind[i] as number;
1277
+ let isBrand: boolean;
1278
+ let tgt: string;
1279
+ let dam: number;
1280
+ if (ind < brandMax) {
1281
+ isBrand = true;
1282
+ tgt = env.brands[ind]?.name ?? "";
1283
+ dam = res.brand[ind] ?? 0;
1284
+ } else {
1285
+ isBrand = false;
1286
+ tgt = env.slays[ind - brandMax]?.name ?? "";
1287
+ dam = res.slay[ind - brandMax] ?? 0;
1288
+ }
1289
+
1290
+ if (groupn > 0) {
1291
+ if (dam !== lastdam) {
1292
+ if (groupn > 2) tbAppend(tb, ", and");
1293
+ else if (groupn === 2) tbAppend(tb, " and");
1294
+ } else if (groupn > 1) {
1295
+ tbAppend(tb, ",");
1296
+ }
1297
+ if (lastIsBrand) tbAppend(tb, " creatures not resistant to");
1298
+ tbAppend(tb, ` ${lastnm}`);
1299
+ }
1300
+ if (dam !== lastdam) {
1301
+ if (i !== 0) tbAppend(tb, ", ");
1302
+ if (dam % 10) {
1303
+ tbAppendC(tb, COLOUR_L_GREEN, `${Math.trunc(dam / 10)}.${dam % 10} vs`);
1304
+ } else {
1305
+ tbAppendC(tb, COLOUR_L_GREEN, `${Math.trunc(dam / 10)} vs`);
1306
+ }
1307
+ groupn = 1;
1308
+ lastdam = dam;
1309
+ } else {
1310
+ groupn++;
1311
+ }
1312
+ lastnm = tgt;
1313
+ lastIsBrand = isBrand;
1314
+ }
1315
+ if (groupn > 0) {
1316
+ if (groupn > 2) tbAppend(tb, ", and");
1317
+ else if (groupn === 2) tbAppend(tb, " and");
1318
+ if (lastIsBrand) tbAppend(tb, " creatures not resistant to");
1319
+ tbAppend(tb, ` ${lastnm}`);
1320
+ }
1321
+
1322
+ if (sortind.length === 0) {
1323
+ hasBrandsOrSlays = false;
1324
+ } else {
1325
+ tbAppend(tb, sortind.length === 1 ? " and " : ", and ");
1326
+ }
1327
+ }
1328
+
1329
+ if (res.normal <= 0) {
1330
+ tbAppendC(tb, COLOUR_L_RED, "0");
1331
+ } else if (res.normal % 10) {
1332
+ tbAppendC(tb, COLOUR_L_GREEN, `${Math.trunc(res.normal / 10)}.${res.normal % 10}`);
1333
+ } else {
1334
+ tbAppendC(tb, COLOUR_L_GREEN, `${Math.trunc(res.normal / 10)}`);
1335
+ }
1336
+
1337
+ if (hasBrandsOrSlays) tbAppend(tb, " vs. others");
1338
+ tbAppend(tb, ".\n");
1339
+ return true;
1340
+ }
1341
+
1342
+ /* ------------------------------------------------------------------ *
1343
+ * describe_combat (obj-info.c L1752).
1344
+ * ------------------------------------------------------------------ */
1345
+
1346
+ function describeCombat(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject): boolean {
1347
+ const bow = deps.bow;
1348
+ const weapon = tvalIsMeleeWeapon(obj.tval);
1349
+ const ammo = deps.currentState.ammoTval === obj.tval && !!bow;
1350
+ const throwingWeapon = weapon && obj.flags.has(OF.THROWING);
1351
+ const rock = tvalIsAmmo(obj.tval) && obj.flags.has(OF.THROWING);
1352
+
1353
+ /* obj_known_misc_combat. */
1354
+ let thrownEffect = false;
1355
+ let range = 0;
1356
+ let heavy = false;
1357
+ if (!weapon && !ammo) {
1358
+ if (tvalIsPotion(obj.tval) && obj.dd !== 0 && obj.ds !== 0 && deps.known.isAware(obj.kind)) {
1359
+ thrownEffect = true;
1360
+ }
1361
+ }
1362
+ if (ammo) {
1363
+ range = 10 * Math.min(6 + 2 * deps.currentState.ammoMult, deps.z.maxRange);
1364
+ }
1365
+ const breakChance = deps.breakageChance(obj);
1366
+ if (weapon) {
1367
+ const s = deps.deriveState(equipWith(deps, obj, deps.weaponSlot), 0, 0);
1368
+ heavy = s.heavyWield;
1369
+ }
1370
+
1371
+ if (!weapon && !ammo && !rock) {
1372
+ if (thrownEffect) {
1373
+ tbAppend(tb, "It can be thrown at creatures with damaging effect.\n");
1374
+ return true;
1375
+ }
1376
+ return false;
1377
+ }
1378
+
1379
+ tbAppendC(tb, COLOUR_L_WHITE, "Combat info:\n");
1380
+ if (heavy) tbAppendC(tb, COLOUR_L_RED, "You are too weak to use this weapon.\n");
1381
+ describeBlows(tb, deps, obj);
1382
+ if (ammo) {
1383
+ tbAppend(tb, "When fired, hits targets up to ");
1384
+ tbAppendC(tb, COLOUR_L_GREEN, `${range}`);
1385
+ tbAppend(tb, " feet away.\n");
1386
+ }
1387
+ if (weapon || ammo) describeDamage(tb, deps, obj, false);
1388
+ if (throwingWeapon || rock) describeDamage(tb, deps, obj, true);
1389
+ if (ammo) {
1390
+ tbAppendC(tb, COLOUR_L_GREEN, `${breakChance}%`);
1391
+ tbAppend(tb, " chance of breaking upon contact.\n");
1392
+ }
1393
+ return true;
1394
+ }
1395
+
1396
+ /* ------------------------------------------------------------------ *
1397
+ * obj_known_digging / describe_digger (obj-info.c L1813 / L1858).
1398
+ * ------------------------------------------------------------------ */
1399
+
1400
+ const DIGGING_NAMES = ["rubble", "magma veins", "quartz veins", "granite"];
1401
+
1402
+ function objKnownDigging(deps: ObjectInfoDeps, obj: GameObject): number[] | null {
1403
+ if (
1404
+ !tvalIsWearable(obj.tval) ||
1405
+ (!tvalIsMeleeWeapon(obj.tval) && (obj.modifiers[OBJ_MOD.TUNNEL] ?? 0) <= 0)
1406
+ ) {
1407
+ return null;
1408
+ }
1409
+ const shadow = shadowOf(deps, obj);
1410
+ if (!tvalIsMeleeWeapon(obj.tval) && !(shadow.modifiers[OBJ_MOD.TUNNEL] ?? 0)) {
1411
+ return null;
1412
+ }
1413
+ const slot = deps.wieldSlot(obj);
1414
+ const state = deps.deriveState(equipWith(deps, obj, slot), 0, 0);
1415
+ const chances = deps.calcDiggingChances(state.skills[SKILL.DIGGING] ?? 0);
1416
+ const deciturns: number[] = [];
1417
+ for (let i = 0; i < 4; i++) {
1418
+ const chance = Math.min(1600, chances[i] ?? 0);
1419
+ deciturns[i] = chance ? Math.trunc(16000 / chance) : 0;
1420
+ }
1421
+ return deciturns;
1422
+ }
1423
+
1424
+ function describeDigger(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject): boolean {
1425
+ const deciturns = objKnownDigging(deps, obj);
1426
+ if (!deciturns) return false;
1427
+ for (let i = 0; i < 4; i++) {
1428
+ const dt = deciturns[i] as number;
1429
+ if (i === 0 && dt > 0) {
1430
+ if (tvalIsMeleeWeapon(obj.tval)) tbAppend(tb, "Clears ");
1431
+ else tbAppend(tb, "With this item, your current weapon clears ");
1432
+ }
1433
+ if (i === 3 || (i !== 0 && dt === 0)) tbAppend(tb, "and ");
1434
+ if (dt === 0) {
1435
+ tbAppendC(tb, COLOUR_L_RED, "doesn't affect ");
1436
+ tbAppend(tb, `${DIGGING_NAMES[i]}.\n`);
1437
+ break;
1438
+ }
1439
+ tbAppend(tb, `${DIGGING_NAMES[i]} in `);
1440
+ if (dt === 10) {
1441
+ tbAppendC(tb, COLOUR_L_GREEN, "1 ");
1442
+ } else if (dt < 100) {
1443
+ tbAppendC(tb, COLOUR_GREEN, `${Math.trunc(dt / 10)}.${dt % 10} `);
1444
+ } else {
1445
+ tbAppendC(tb, dt < 1000 ? COLOUR_YELLOW : COLOUR_RED, `${Math.trunc((dt + 5) / 10)} `);
1446
+ }
1447
+ tbAppend(tb, `turn${dt === 10 ? "" : "s"}${i === 3 ? ".\n" : ", "}`);
1448
+ }
1449
+ return true;
1450
+ }
1451
+
1452
+ /* ------------------------------------------------------------------ *
1453
+ * describe_light (obj-info.c L1914 / L1955).
1454
+ * ------------------------------------------------------------------ */
1455
+
1456
+ function describeLight(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject, mode: number): boolean {
1457
+ const shadow = shadowOf(deps, obj);
1458
+ const isLight = tvalIsLight(obj.tval);
1459
+ if (!isLight && (obj.modifiers[OBJ_MOD.LIGHT] ?? 0) <= 0) return false;
1460
+ let intensity = 0;
1461
+ if (obj.flags.has(OF.LIGHT_2)) intensity = 2;
1462
+ else if (obj.flags.has(OF.LIGHT_3)) intensity = 3;
1463
+ intensity += shadow.modifiers[OBJ_MOD.LIGHT] ?? 0;
1464
+ if (intensity === 0) return false;
1465
+ const noFuel = shadow.flags.has(OF.NO_FUEL);
1466
+ const usesFuel = !(noFuel || shadow.artifact);
1467
+ const refuelTurns = isLight && shadow.flags.has(OF.TAKES_FUEL) ? deps.z.fuelLamp : 0;
1468
+ const terse = (mode & OINFO.TERSE) !== 0;
1469
+
1470
+ if (isLight) {
1471
+ tbAppend(tb, "Intensity ");
1472
+ tbAppendC(tb, COLOUR_L_GREEN, `${intensity}`);
1473
+ tbAppend(tb, " light.");
1474
+ if (!obj.artifact && !usesFuel) tbAppend(tb, " No fuel required.");
1475
+ if (!terse) {
1476
+ if (refuelTurns) {
1477
+ tbAppend(tb, ` Refills other lanterns up to ${refuelTurns} turns of fuel.`);
1478
+ } else {
1479
+ tbAppend(tb, " Cannot be refueled.");
1480
+ }
1481
+ }
1482
+ tbAppend(tb, "\n");
1483
+ }
1484
+ return true;
1485
+ }
1486
+
1487
+ /* ------------------------------------------------------------------ *
1488
+ * describe_book / describe_effect (obj-info.c L1990 / L2060).
1489
+ * ------------------------------------------------------------------ */
1490
+
1491
+ function describeBook(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject): boolean {
1492
+ if (!(deps.canBrowse?.(obj) ?? false)) return false;
1493
+ tbAppend(tb, "\nYou can read this book.\n");
1494
+ return true;
1495
+ }
1496
+
1497
+ function describeEffect(
1498
+ tb: Textblock,
1499
+ deps: ObjectInfoDeps,
1500
+ obj: GameObject,
1501
+ shadow: GameObject,
1502
+ subjective: boolean,
1503
+ ): boolean {
1504
+ const effRecords = obj.activation?.effect ?? obj.effect ?? null;
1505
+ if (!effRecords || effRecords.length === 0) return false;
1506
+
1507
+ const storeConsumable = (deps.inStore ?? false) && tvalIsUseable(obj.tval);
1508
+ const known = objectEffectIsKnown(obj, shadow) || storeConsumable;
1509
+
1510
+ /* Effect not known: mouth platitudes. */
1511
+ if (!known) {
1512
+ if (tvalIsEdible(obj.tval)) tbAppend(tb, "It can be eaten.\n");
1513
+ else if (tvalIsPotion(obj.tval)) tbAppend(tb, "It can be drunk.\n");
1514
+ else if (tvalIsScroll(obj.tval)) tbAppend(tb, "It can be read.\n");
1515
+ else if (tvalIsWand(obj.tval)) tbAppend(tb, "It requires a target. It can be used.");
1516
+ else if (tvalIsStaff(obj.tval)) tbAppend(tb, "It can be used.");
1517
+ else tbAppend(tb, "It may require a target. It can be used.");
1518
+ return true;
1519
+ }
1520
+
1521
+ const aimed = deps.effect.aimed;
1522
+ let minTime = 0;
1523
+ let maxTime = 0;
1524
+ if (rvMax(obj.time) > 0) {
1525
+ minTime = rvMin(obj.time);
1526
+ maxTime = rvMax(obj.time);
1527
+ }
1528
+ const failureChance =
1529
+ tvalIsEdible(obj.tval) || tvalIsPotion(obj.tval) || tvalIsScroll(obj.tval)
1530
+ ? 0
1531
+ : deps.effect.deviceFailure;
1532
+
1533
+ if (obj.activation && obj.activation.desc) {
1534
+ if (aimed) tbAppend(tb, "It requires a target. ");
1535
+ tbAppend(tb, "When used, it ");
1536
+ tbAppend(tb, obj.activation.desc);
1537
+ } else {
1538
+ const level =
1539
+ obj.artifact?.level ?? obj.activation?.level ?? obj.kind.level;
1540
+ const deviceSkill = deps.currentState.skills[SKILL.DEVICE] ?? 0;
1541
+ const boost = Math.max(Math.trunc((deviceSkill - level) / 2), 0);
1542
+ let prefix: string;
1543
+ if (tvalIsEdible(obj.tval)) {
1544
+ prefix = aimed ? "It requires a target. When eaten, it " : "When eaten, it ";
1545
+ } else if (tvalIsPotion(obj.tval)) {
1546
+ prefix = aimed ? "It requires a target. When quaffed, it " : "When quaffed, it ";
1547
+ } else if (tvalIsScroll(obj.tval)) {
1548
+ prefix = aimed ? "It requires a target. When read, it " : "When read, it ";
1549
+ } else {
1550
+ prefix = aimed ? "It requires a target. When used, it " : "When used, it ";
1551
+ }
1552
+ const tbe = deps.effect.describe(prefix, boost, false);
1553
+ if (tbe === null) return false;
1554
+ tbAppend(tb, tbe);
1555
+ }
1556
+
1557
+ tbAppend(tb, ".\n");
1558
+
1559
+ if (minTime || maxTime) {
1560
+ const multiplier = subjective ? deps.speedMultiplier : 10;
1561
+ tbAppend(tb, "Takes ");
1562
+ minTime = Math.trunc((minTime * multiplier) / 10);
1563
+ maxTime = Math.trunc((maxTime * multiplier) / 10);
1564
+ tbAppendC(tb, COLOUR_L_GREEN, `${minTime}`);
1565
+ if (minTime !== maxTime) {
1566
+ tbAppend(tb, " to ");
1567
+ tbAppendC(tb, COLOUR_L_GREEN, `${maxTime}`);
1568
+ }
1569
+ tbAppend(tb, " turns to recharge");
1570
+ if (subjective && deps.currentState.speed !== 110) {
1571
+ tbAppend(tb, " at your current speed");
1572
+ }
1573
+ tbAppend(tb, ".\n");
1574
+ }
1575
+
1576
+ if (failureChance > 0) {
1577
+ tbAppend(
1578
+ tb,
1579
+ `Your chance of success is ${Math.trunc((1000 - failureChance) / 10)}.${(1000 - failureChance) % 10}%\n`,
1580
+ );
1581
+ }
1582
+ return true;
1583
+ }
1584
+
1585
+ /* ------------------------------------------------------------------ *
1586
+ * describe_origin / describe_flavor_text (obj-info.c L2177 / L2252).
1587
+ * ------------------------------------------------------------------ */
1588
+
1589
+ function describeOrigin(tb: Textblock, deps: ObjectInfoDeps, obj: GameObject, terse: boolean): boolean {
1590
+ /* Only in chardumps if wieldable; inspect is never terse. */
1591
+ if (terse && !tvalIsWearable(obj.tval)) return false;
1592
+
1593
+ let origin = obj.origin;
1594
+ if (obj.origin === ORIGIN.DROP_MIMIC && obj.mimickingMIdx !== 0) {
1595
+ origin = ORIGIN.FLOOR;
1596
+ }
1597
+
1598
+ const lootSpot = obj.originDepth
1599
+ ? `at ${obj.originDepth * 50} feet (level ${obj.originDepth})`
1600
+ : "in town";
1601
+
1602
+ let dropper = "monster lost to history";
1603
+ let unique = false;
1604
+ let comma = false;
1605
+ if (obj.originRace) {
1606
+ const race = deps.raceOrigin?.(obj.originRace);
1607
+ if (race) {
1608
+ dropper = race.name;
1609
+ unique = race.unique;
1610
+ comma = race.comma;
1611
+ }
1612
+ }
1613
+ const article = isAVowel(dropper[0] ?? "") ? "an " : "a ";
1614
+ let name = unique ? dropper : article + dropper;
1615
+ if (comma) name += ",";
1616
+
1617
+ const entry = ORIGIN_ENTRIES[origin];
1618
+ if (!entry) return false;
1619
+ switch (entry.args) {
1620
+ case -1:
1621
+ return false;
1622
+ case 0:
1623
+ tbAppend(tb, entry.description);
1624
+ break;
1625
+ case 1:
1626
+ tbAppend(tb, sprintfS(entry.description, lootSpot));
1627
+ break;
1628
+ case 2:
1629
+ tbAppend(tb, sprintfS(entry.description, name, lootSpot));
1630
+ break;
1631
+ default:
1632
+ break;
1633
+ }
1634
+ tbAppend(tb, "\n\n");
1635
+ return true;
1636
+ }
1637
+
1638
+ function describeFlavorText(
1639
+ tb: Textblock,
1640
+ deps: ObjectInfoDeps,
1641
+ obj: GameObject,
1642
+ shadow: GameObject,
1643
+ ego: boolean,
1644
+ ): void {
1645
+ if (!deps.randarts && obj.artifact && shadow.artifact && obj.artifact.text) {
1646
+ tbAppend(tb, `${obj.artifact.text}\n\n`);
1647
+ } else if (deps.known.isAware(obj.kind) || ego) {
1648
+ let didDesc = false;
1649
+ if (!ego && obj.kind.text) {
1650
+ tbAppend(tb, obj.kind.text);
1651
+ didDesc = true;
1652
+ }
1653
+ if ((ego || shadow.ego !== null) && obj.ego?.text) {
1654
+ if (didDesc) tbAppend(tb, " ");
1655
+ tbAppend(tb, `${obj.ego.text}\n\n`);
1656
+ } else if (didDesc) {
1657
+ tbAppend(tb, "\n\n");
1658
+ }
1659
+ }
1660
+ }
1661
+
1662
+ /* ------------------------------------------------------------------ *
1663
+ * object_info_out (obj-info.c L2315).
1664
+ * ------------------------------------------------------------------ */
1665
+
1666
+ /**
1667
+ * object_info (obj-info.c L2393) folded with object_info_out: build the run
1668
+ * stream for an object. Inspect calls with mode = OINFO.SUBJ (the ego / terse
1669
+ * / fake / spoil bits stay off). The caller must OR in OINFO.SUBJ, matching
1670
+ * upstream object_info().
1671
+ */
1672
+ export function objectInfo(obj: GameObject, mode: number, deps: ObjectInfoDeps): Textblock {
1673
+ const tb = tbNew();
1674
+ const terse = (mode & OINFO.TERSE) !== 0;
1675
+ const subjective = (mode & OINFO.SUBJ) !== 0;
1676
+ const ego = (mode & OINFO.EGO) !== 0;
1677
+
1678
+ const shadow = shadowOf(deps, obj);
1679
+
1680
+ /* Unaware objects get simple descriptions (the port's shadow.kind always
1681
+ mirrors obj.kind, matching object_set_base_known; the is_unknown grid
1682
+ placeholder is not modelled). */
1683
+ if (obj.kind !== shadow.kind) {
1684
+ tbAppend(tb, "\n\nYou do not know what this is.\n");
1685
+ return tb;
1686
+ }
1687
+
1688
+ /* get_known_flags: non-ego, non-terse -> the shadow's flags. */
1689
+ const flags = shadow.flags;
1690
+ const el = getKnownElements(obj, shadow, deps.player, mode);
1691
+
1692
+ if (subjective) describeOrigin(tb, deps, obj, terse);
1693
+ if (!terse) describeFlavorText(tb, deps, obj, shadow, ego);
1694
+
1695
+ let something = false;
1696
+ if (
1697
+ !objectFullyKnown(obj, shadow, deps.player, deps.env) &&
1698
+ shadow.notice & OBJ_NOTICE.ASSESSED &&
1699
+ !tvalIsUseable(obj.tval)
1700
+ ) {
1701
+ tbAppend(tb, "You do not know the full extent of this item's powers.\n");
1702
+ something = true;
1703
+ }
1704
+
1705
+ const aware = deps.known.isAware(obj.kind);
1706
+ if (describeCurses(tb, shadow, deps.env)) something = true;
1707
+ if (describeStats(tb, shadow, deps.env, mode, aware)) something = true;
1708
+ if (describeSlays(tb, shadow, deps.env)) something = true;
1709
+ if (describeBrands(tb, shadow, deps.env)) something = true;
1710
+ if (describeElements(tb, el, deps.projections)) something = true;
1711
+ if (describeProtects(tb, flags, deps.env)) something = true;
1712
+ if (describeIgnores(tb, el, deps.projections)) something = true;
1713
+ if (describeHates(tb, el, deps.projections)) something = true;
1714
+ if (describeSustains(tb, flags, deps.env)) something = true;
1715
+ if (describeMiscMagic(tb, flags, deps.env)) something = true;
1716
+ if (describeLight(tb, deps, obj, mode)) something = true;
1717
+ if (describeBook(tb, deps, obj)) something = true;
1718
+ /* describe_ego is skipped for inspect (ego bit off). */
1719
+ if (something) tbAppend(tb, "\n");
1720
+
1721
+ if (!ego) {
1722
+ if (describeEffect(tb, deps, obj, shadow, subjective)) {
1723
+ something = true;
1724
+ tbAppend(tb, "\n");
1725
+ }
1726
+ if (subjective && describeCombat(tb, deps, obj)) {
1727
+ something = true;
1728
+ tbAppend(tb, "\n");
1729
+ }
1730
+ if (!terse && subjective && describeDigger(tb, deps, obj)) something = true;
1731
+ }
1732
+
1733
+ if (!something && !terse) {
1734
+ tbAppend(tb, "\n\n\nThis item does not seem to possess any special abilities.");
1735
+ }
1736
+ return tb;
1737
+ }