@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,1577 @@
1
+ /**
2
+ * The player's object-knowledge (the "rune" learning system), ported from
3
+ * reference/src/obj-knowledge.c (Angband 4.2.6).
4
+ *
5
+ * The learn-by-use half is fully ported: runes are learned on wield
6
+ * (object_learn_on_wield), on attack and defend (equip_learn_on_melee_attack /
7
+ * _ranged_attack / _on_defend, missile_learn_on_ranged_attack), when a flag or
8
+ * element fires in play (equip_learn_flag / equip_learn_element), over time
9
+ * (equip_learn_after_time), from brands/slays biting a monster
10
+ * (player_learn_brand/slay via combat/brand-slay.ts), plus the racial innates
11
+ * at birth (player_learn_innate) and the learn-everything wizard ramp
12
+ * (player_learn_all_runes).
13
+ *
14
+ * The modifier runes gate REAL play: calc_bonuses (player-calcs.c L1942-1981)
15
+ * multiplies every equipped item's modifier by p->obj_k->modifiers, so an
16
+ * unlearned modifier is INERT. Flags, resists, and the to_a/to_h/to_d combat
17
+ * bonuses always apply for the real state and their runes feed the DISPLAYED
18
+ * known_state (character sheet / inspect), which lands with the display task;
19
+ * the knowledge itself is tracked here exactly as upstream so the display
20
+ * work is pure presentation.
21
+ *
22
+ * DEFERRED (ledgered in parity/ledger/obj-knowledge.yaml): the per-object
23
+ * obj->known twin (display-only shadow copies: "had a chance to notice"
24
+ * markers, object_fully_known short-circuits, update_player_object_knowledge's
25
+ * gear/store sweep), rune inscriptions (rune_note), monster-lore learning from
26
+ * brands/slays (lore is #24), and shapechange learning (shapes are bound raw).
27
+ */
28
+
29
+ import { FLAG_START, FlagSet, NO_FLAG } from "../bitflag.js";
30
+ import type { RandomValue } from "../rng.js";
31
+ import type { GameObject } from "./object.js";
32
+ import { sameMonstersSlain, tvalIsBodyArmor, tvalIsJewelry } from "./object.js";
33
+ import type {
34
+ Brand,
35
+ Curse,
36
+ EgoItem,
37
+ ObjectKind,
38
+ ObjectProperty,
39
+ Slay,
40
+ } from "./types.js";
41
+ import {
42
+ ELEM_HIGH_MAX,
43
+ ELEM_MAX,
44
+ OBJ_MOD_MAX,
45
+ OBJ_PROPERTY,
46
+ OF_SIZE,
47
+ OFID,
48
+ OFT,
49
+ } from "./types.js";
50
+ import { OF } from "../generated/index.js";
51
+ import { OBJECT_FLAG_ENTRIES } from "../generated/object-flags.js";
52
+ import { OBJ_MOD } from "../generated/object-modifiers.js";
53
+ import { STAT_MAX } from "../player/types.js";
54
+ import type { Player } from "../player/player.js";
55
+
56
+ /** obj->notice bits (object.h). */
57
+ export const OBJ_NOTICE = {
58
+ WORN: 0x01,
59
+ ASSESSED: 0x02,
60
+ IGNORE: 0x04,
61
+ IMAGINED: 0x08,
62
+ } as const;
63
+
64
+ /**
65
+ * The registry tables and equipment access rune learning reads. Built once
66
+ * per game (session/game.ts wireGame) from the bound registries; the harness
67
+ * provides an inert default for worldless tests.
68
+ */
69
+ export interface RuneEnv {
70
+ brands: readonly (Brand | null)[];
71
+ slays: readonly (Slay | null)[];
72
+ curses: readonly (Curse | null)[];
73
+ properties: readonly (ObjectProperty | null)[];
74
+ /** Element rune names (upstream projections[i].name: "acid", ...). */
75
+ elementNames: readonly string[];
76
+ /** slot_object(p, i): the equipped object in body slot i, or null. */
77
+ slotObject(slot: number): GameObject | null;
78
+ /** randcalc_varies, for object_has_standard_to_h on body armor. */
79
+ randcalcVaries(v: RandomValue): boolean;
80
+ /** Flavor knowledge, for object_flavor_tried on wield. */
81
+ flavor?: FlavorKnowledge;
82
+ /** msg() sink for rune / flag / modifier messages. */
83
+ msg?(text: string): void;
84
+ }
85
+
86
+ /** Optional registry tables for makeRuneEnv (inert defaults when absent). */
87
+ export interface RuneEnvTables {
88
+ brands?: readonly (Brand | null)[];
89
+ slays?: readonly (Slay | null)[];
90
+ curses?: readonly (Curse | null)[];
91
+ properties?: readonly (ObjectProperty | null)[];
92
+ elementNames?: readonly string[];
93
+ flavor?: FlavorKnowledge;
94
+ msg?(text: string): void;
95
+ }
96
+
97
+ /**
98
+ * Assemble a RuneEnv from equipment access plus whatever registry tables the
99
+ * caller has; missing tables default to empty (learning against them is a
100
+ * no-op), which keeps worldless harness tests total.
101
+ */
102
+ export function makeRuneEnv(
103
+ slotObject: (slot: number) => GameObject | null,
104
+ randcalcVaries: (v: RandomValue) => boolean,
105
+ tables: RuneEnvTables = {},
106
+ ): RuneEnv {
107
+ return {
108
+ brands: tables.brands ?? [null],
109
+ slays: tables.slays ?? [null],
110
+ curses: tables.curses ?? [null],
111
+ properties: tables.properties ?? [null],
112
+ elementNames: tables.elementNames ?? [],
113
+ slotObject,
114
+ randcalcVaries,
115
+ ...(tables.flavor ? { flavor: tables.flavor } : {}),
116
+ ...(tables.msg ? { msg: tables.msg } : {}),
117
+ };
118
+ }
119
+
120
+ function lookupProp(
121
+ env: RuneEnv,
122
+ type: number,
123
+ propIndex: number,
124
+ ): ObjectProperty | null {
125
+ for (const p of env.properties) {
126
+ if (p && p.type === type && p.propIndex === propIndex) return p;
127
+ }
128
+ return null;
129
+ }
130
+
131
+ /** "You have learned the rune of %s." (player_learn_rune's msgt). */
132
+ function runeMsg(env: RuneEnv, name: string | null): void {
133
+ if (name) env.msg?.(`You have learned the rune of ${name}.`);
134
+ }
135
+
136
+ /**
137
+ * Expand the `{tag}` forms in an obj_property message (obj-properties.c
138
+ * L111-136).
139
+ *
140
+ * Ported as the C parses rather than as a pair of regex replacements, because the
141
+ * two disagree on three points and every one of them is reachable from a mod's own
142
+ * `msg:` line (a content mod may contribute object_property records):
143
+ *
144
+ * - Only `name` is substituted. Any OTHER well-formed tag - `{level}`, `{foo}` -
145
+ * is consumed and replaced with NOTHING (L121-127 substitutes nothing unless the
146
+ * tag matches), where a `{name}`-only replace would leave it in the message.
147
+ * - An UNCLOSED brace loses the brace and keeps the rest (L129-132 advances past
148
+ * the `{` alone), where a replace would print it.
149
+ * - `%s` is NOT a substitution here. The C builds `buf` and then calls
150
+ * `msg("%s", buf)` (L138), so a literal `%s` in a property message stays
151
+ * literal. The port used to swap the object name in for it, which is an invented
152
+ * behaviour - no shipped record contains `%s`, so it was latent, and a mod's
153
+ * message is exactly where it would have surfaced.
154
+ *
155
+ * The tag test is upstream's `strncmp(tag, "name", 4)` (L125), a PREFIX compare on
156
+ * the live string, so `{names}` matches too. Kept, wart and all.
157
+ */
158
+ function expandPropertyTags(msg: string, name: string): string {
159
+ let out = "";
160
+ let cursor = 0;
161
+ for (;;) {
162
+ const next = msg.indexOf("{", cursor);
163
+ if (next < 0) break;
164
+ /* The text leading up to this { (L114-115). */
165
+ out += msg.slice(cursor, next);
166
+ let s = next + 1;
167
+ /* isalpha() under the C locale: ASCII letters only (L118). */
168
+ while (s < msg.length && /[A-Za-z]/.test(msg[s]!)) s++;
169
+ if (msg[s] === "}") {
170
+ if (msg.slice(next + 1, s).startsWith("name")) out += name;
171
+ cursor = s + 1;
172
+ } else {
173
+ cursor = next + 1; /* an invalid tag: skip it */
174
+ }
175
+ }
176
+ return out + msg.slice(cursor);
177
+ }
178
+
179
+ /**
180
+ * flag_message (obj-properties.c:86-139): the property's message for a flag the
181
+ * player has just noticed, with the object's base name substituted for `{name}`.
182
+ *
183
+ * Takes no player, exactly as the C does. The `p->upkeep->playing` gate belongs to
184
+ * TWO of the four call sites (obj-knowledge.c:1664 and :1857) and NOT to the other
185
+ * two (:2110 equip_learn_flag, :2202 equip_learn_after_time). The port used to hold
186
+ * the gate inside this function, which silently applied it to all four and
187
+ * suppressed messages upstream sends - so the gate now lives at the call sites that
188
+ * have it, and the shape of that decision is visible where the C makes it.
189
+ */
190
+ function flagMessage(env: RuneEnv, flag: number, oName: string): void {
191
+ const prop = lookupProp(env, OBJ_PROPERTY.FLAG, flag);
192
+ /* No property record at all: upstream reports the bug rather than falling
193
+ * silent, and distinguishes an out-of-range index from a flag that simply has
194
+ * no object_property.txt entry (L97-107). Both are reachable through a mod that
195
+ * removes or mistypes a record. */
196
+ if (!prop) {
197
+ if (flag < 0 || flag >= OF.MAX) {
198
+ env.msg?.(`Bug: invalid flag index, ${flag}, passed to flag_message().`);
199
+ } else {
200
+ env.msg?.(
201
+ `Bug: flag '${objectFlagName(flag)}' (index ${flag}) noticed but has no entry in object_property.txt.`,
202
+ );
203
+ }
204
+ return;
205
+ }
206
+ if (!prop.msg) return;
207
+ env.msg?.(expandPropertyTags(prop.msg, oName));
208
+ }
209
+
210
+ /**
211
+ * list_obj_flag_names[flag] (init.c:110-116), whose element 0 is "NONE" and whose
212
+ * rest comes from list-object-flags.h - so OF_<name> indexes it directly and the
213
+ * generated entries tuple is one behind.
214
+ */
215
+ function objectFlagName(flag: number): string {
216
+ return OBJECT_FLAG_ENTRIES[flag - 1]?.name ?? "NONE";
217
+ }
218
+
219
+ /** ODESC_BASE approximation until object_desc lands: the kind's plain name. */
220
+ export function objBaseName(obj: GameObject): string {
221
+ return obj.kind.name.replace(/[~&]/g, "").trim();
222
+ }
223
+ const baseName = objBaseName;
224
+
225
+ /* ------------------------------------------------------------------ *
226
+ * player_knows_* accessors.
227
+ * ------------------------------------------------------------------ */
228
+
229
+ /** player_knows_brand. */
230
+ export function playerKnowsBrand(p: Player, i: number): boolean {
231
+ return p.objKnown.brands[i] ?? false;
232
+ }
233
+
234
+ /** player_knows_slay. */
235
+ export function playerKnowsSlay(p: Player, i: number): boolean {
236
+ return p.objKnown.slays[i] ?? false;
237
+ }
238
+
239
+ /** player_knows_curse. */
240
+ export function playerKnowsCurse(p: Player, i: number): boolean {
241
+ return (p.objKnown.curses[i] ?? 0) > 0;
242
+ }
243
+
244
+ /* ------------------------------------------------------------------ *
245
+ * player_learn_rune, split by variety (the port has no flat rune list;
246
+ * each case of the upstream switch is a typed function).
247
+ * ------------------------------------------------------------------ */
248
+
249
+ const COMBAT_RUNE_NAMES = {
250
+ toA: "enchantment to armor",
251
+ toH: "enchantment to hit",
252
+ toD: "enchantment to damage",
253
+ } as const;
254
+
255
+ /** RUNE_VAR_COMBAT: learn one of the three combat runes. */
256
+ export function playerLearnCombat(
257
+ p: Player,
258
+ env: RuneEnv,
259
+ which: "toA" | "toH" | "toD",
260
+ message = true,
261
+ ): boolean {
262
+ if (p.objKnown[which]) return false;
263
+ p.objKnown[which] = 1;
264
+ if (message) runeMsg(env, COMBAT_RUNE_NAMES[which]);
265
+ return true;
266
+ }
267
+
268
+ /** RUNE_VAR_MOD: learn a modifier rune. */
269
+ export function playerLearnMod(
270
+ p: Player,
271
+ env: RuneEnv,
272
+ i: number,
273
+ message = true,
274
+ ): boolean {
275
+ if (p.objKnown.modifiers[i]) return false;
276
+ p.objKnown.modifiers[i] = 1;
277
+ if (message) {
278
+ runeMsg(env, lookupProp(env, OBJ_PROPERTY.MOD, i)?.name ??
279
+ lookupProp(env, OBJ_PROPERTY.STAT, i)?.name ?? null);
280
+ }
281
+ return true;
282
+ }
283
+
284
+ /** RUNE_VAR_RESIST: learn an element rune (high elements only, as the list). */
285
+ export function playerLearnResist(
286
+ p: Player,
287
+ env: RuneEnv,
288
+ elem: number,
289
+ message = true,
290
+ ): boolean {
291
+ if (elem < 0 || elem >= ELEM_HIGH_MAX) return false;
292
+ const el = p.objKnown.elInfo[elem];
293
+ if (!el || el.resLevel) return false;
294
+ el.resLevel = 1;
295
+ if (message) runeMsg(env, env.elementNames[elem] ?? null);
296
+ return true;
297
+ }
298
+
299
+ /** RUNE_VAR_FLAG: learn an object-flag rune. */
300
+ export function playerLearnFlagRune(
301
+ p: Player,
302
+ env: RuneEnv,
303
+ flag: number,
304
+ message = true,
305
+ ): boolean {
306
+ if (p.objKnown.flags.has(flag)) return false;
307
+ p.objKnown.flags.on(flag);
308
+ if (message) {
309
+ runeMsg(env, lookupProp(env, OBJ_PROPERTY.FLAG, flag)?.name ?? null);
310
+ }
311
+ return true;
312
+ }
313
+
314
+ /**
315
+ * RUNE_VAR_BRAND: learn a brand rune; all brands sharing the name are learned
316
+ * together (a rune covers "fire" whatever the multiplier).
317
+ */
318
+ export function playerLearnBrand(
319
+ p: Player,
320
+ env: RuneEnv,
321
+ index: number,
322
+ message = true,
323
+ ): boolean {
324
+ if (playerKnowsBrand(p, index)) return false;
325
+ const name = env.brands[index]?.name;
326
+ if (!name) return false;
327
+ for (let j = 1; j < env.brands.length; j++) {
328
+ if (env.brands[j]?.name === name) p.objKnown.brands[j] = true;
329
+ }
330
+ if (message) runeMsg(env, name);
331
+ return true;
332
+ }
333
+
334
+ /**
335
+ * RUNE_VAR_SLAY: learn a slay rune; all slays hitting the same monsters
336
+ * (same_monsters_slain) are learned together.
337
+ */
338
+ export function playerLearnSlay(
339
+ p: Player,
340
+ env: RuneEnv,
341
+ index: number,
342
+ message = true,
343
+ ): boolean {
344
+ if (playerKnowsSlay(p, index)) return false;
345
+ const s = env.slays[index];
346
+ if (!s) return false;
347
+ for (let j = 1; j < env.slays.length; j++) {
348
+ if (sameMonstersSlain(env.slays, index, j)) p.objKnown.slays[j] = true;
349
+ }
350
+ if (message) runeMsg(env, s.name);
351
+ return true;
352
+ }
353
+
354
+ /** RUNE_VAR_CURSE: learn a curse rune. */
355
+ export function playerLearnCurse(
356
+ p: Player,
357
+ env: RuneEnv,
358
+ index: number,
359
+ message = true,
360
+ ): boolean {
361
+ if (playerKnowsCurse(p, index)) return false;
362
+ if (!env.curses[index]) return false;
363
+ p.objKnown.curses[index] = 1;
364
+ if (message) runeMsg(env, env.curses[index]?.name ?? null);
365
+ return true;
366
+ }
367
+
368
+ /* ------------------------------------------------------------------ *
369
+ * Masks and object predicates.
370
+ * ------------------------------------------------------------------ */
371
+
372
+ /**
373
+ * create_obj_flag_mask(f, true, id, OFT_MAX): every OF_* flag whose property
374
+ * has the given OFID_* identify type.
375
+ */
376
+ export function objFlagMaskById(env: RuneEnv, id: number): FlagSet {
377
+ const mask = new FlagSet(OF_SIZE);
378
+ for (const prop of env.properties) {
379
+ if (prop && prop.type === OBJ_PROPERTY.FLAG && prop.idType === id) {
380
+ mask.on(prop.propIndex);
381
+ }
382
+ }
383
+ return mask;
384
+ }
385
+
386
+ /**
387
+ * player_outfit's obvious-flag knowledge (player-birth.c L597-602): at birth the
388
+ * player knows every LIGHT / DIG / THROW / CURSE_ONLY subtype object flag. These
389
+ * are the non-rune "on wield" flags (init_rune skips their subtypes), so without
390
+ * this a mundane torch / digger / thrown item would read as not-fully-known and
391
+ * show a spurious "{??}" in stores and lists. Marking them known here makes such
392
+ * items fully known the moment they are seen, exactly as upstream. Mutates the
393
+ * passed flag set in place.
394
+ */
395
+ export function learnBirthObviousFlags(
396
+ known: FlagSet,
397
+ properties: readonly (ObjectProperty | null)[],
398
+ ): void {
399
+ for (const prop of properties) {
400
+ if (!prop || prop.type !== OBJ_PROPERTY.FLAG) continue;
401
+ if (
402
+ prop.subtype === OFT.LIGHT ||
403
+ prop.subtype === OFT.DIG ||
404
+ prop.subtype === OFT.THROW ||
405
+ prop.subtype === OFT.CURSE_ONLY
406
+ ) {
407
+ known.on(prop.propIndex);
408
+ }
409
+ }
410
+ }
411
+
412
+ /** sustain_flag(stat): the OF_SUST_* flag for a stat (contiguous block). */
413
+ export function sustainFlag(stat: number): number {
414
+ if (stat < 0 || stat >= STAT_MAX) return -1;
415
+ return OF.SUST_STR + stat;
416
+ }
417
+
418
+ /**
419
+ * object_has_standard_to_h: body armor with a fixed kind to_h matches the
420
+ * kind's base; anything else is standard only at to_h == 0.
421
+ */
422
+ export function objectHasStandardToH(env: RuneEnv, obj: GameObject): boolean {
423
+ if (tvalIsBodyArmor(obj.tval) && !env.randcalcVaries(obj.kind.toH)) {
424
+ return obj.toH === obj.kind.toH.base;
425
+ }
426
+ return obj.toH === 0;
427
+ }
428
+
429
+ /* ------------------------------------------------------------------ *
430
+ * object_curses_find_*: notice properties supplied by an object's curses,
431
+ * learning both the property rune and the curse rune.
432
+ * ------------------------------------------------------------------ */
433
+
434
+ function curseLearnCombat(
435
+ p: Player,
436
+ env: RuneEnv,
437
+ obj: GameObject,
438
+ which: "toA" | "toH" | "toD",
439
+ ): void {
440
+ if (!obj.curses) return;
441
+ for (let i = 1; i < env.curses.length; i++) {
442
+ const c = env.curses[i];
443
+ if (!obj.curses[i]?.power || !c) continue;
444
+ if (c.obj[which] !== 0) {
445
+ playerLearnCombat(p, env, which);
446
+ playerLearnCurse(p, env, i);
447
+ }
448
+ }
449
+ }
450
+
451
+ export function objectCursesFindToA(p: Player, env: RuneEnv, obj: GameObject): void {
452
+ curseLearnCombat(p, env, obj, "toA");
453
+ }
454
+ export function objectCursesFindToH(p: Player, env: RuneEnv, obj: GameObject): void {
455
+ curseLearnCombat(p, env, obj, "toH");
456
+ }
457
+ export function objectCursesFindToD(p: Player, env: RuneEnv, obj: GameObject): void {
458
+ curseLearnCombat(p, env, obj, "toD");
459
+ }
460
+
461
+ /** object_curses_find_flags: learn test-mask flags carried by curses. */
462
+ export function objectCursesFindFlags(
463
+ p: Player,
464
+ env: RuneEnv,
465
+ obj: GameObject,
466
+ testFlags: FlagSet,
467
+ ): boolean {
468
+ if (!obj.curses) return false;
469
+ let found = false;
470
+ const oName = baseName(obj);
471
+ for (let i = 1; i < env.curses.length; i++) {
472
+ const c = env.curses[i];
473
+ if (!obj.curses[i]?.power || !c) continue;
474
+ for (let flag = 1; flag < OF.MAX; flag++) {
475
+ if (!c.obj.flags.has(flag) || !testFlags.has(flag)) continue;
476
+ if (!p.objKnown.flags.has(flag)) {
477
+ found = true;
478
+ playerLearnFlagRune(p, env, flag);
479
+ /* p->upkeep->playing (obj-knowledge.c:1664): this call site gates, and
480
+ * two of the four do not. */
481
+ if (p.upkeep.playing) flagMessage(env, flag, oName);
482
+ }
483
+ playerLearnCurse(p, env, i);
484
+ }
485
+ }
486
+ return found;
487
+ }
488
+
489
+ /** object_curses_find_modifiers: learn modifier runes carried by curses. */
490
+ export function objectCursesFindModifiers(
491
+ p: Player,
492
+ env: RuneEnv,
493
+ obj: GameObject,
494
+ ): void {
495
+ if (!obj.curses) return;
496
+ for (let i = 1; i < env.curses.length; i++) {
497
+ const c = env.curses[i];
498
+ if (!obj.curses[i]?.power || !c) continue;
499
+ for (let j = 0; j < OBJ_MOD_MAX; j++) {
500
+ if (c.obj.modifiers[j]) {
501
+ if (!p.objKnown.modifiers[j]) {
502
+ playerLearnMod(p, env, j);
503
+ if (p.upkeep.playing) modMessage(env, obj, j);
504
+ }
505
+ playerLearnCurse(p, env, i);
506
+ }
507
+ }
508
+ }
509
+ }
510
+
511
+ /** object_curses_find_element: learn an element rune carried by curses. */
512
+ export function objectCursesFindElement(
513
+ p: Player,
514
+ env: RuneEnv,
515
+ obj: GameObject,
516
+ elem: number,
517
+ ): boolean {
518
+ if (!obj.curses) return false;
519
+ let found = false;
520
+ const oName = baseName(obj);
521
+ for (let i = 1; i < env.curses.length; i++) {
522
+ const c = env.curses[i];
523
+ if (!obj.curses[i]?.power || !c) continue;
524
+ if ((c.obj.elInfo[elem]?.resLevel ?? 0) !== 0) {
525
+ if (!(p.objKnown.elInfo[elem]?.resLevel ?? 0)) {
526
+ env.msg?.(`Your ${oName} glows.`);
527
+ playerLearnResist(p, env, elem);
528
+ }
529
+ playerLearnCurse(p, env, i);
530
+ found = true;
531
+ }
532
+ }
533
+ return found;
534
+ }
535
+
536
+ /* ------------------------------------------------------------------ *
537
+ * Learning from individual objects.
538
+ * ------------------------------------------------------------------ */
539
+
540
+ /** mod_message (obj-knowledge.c L1492): "You feel..." on noticing a modifier. */
541
+ function modMessage(env: RuneEnv, obj: GameObject, mod: number): void {
542
+ if (!env.msg) return;
543
+ const v = obj.modifiers[mod] ?? 0;
544
+ const both = (pos: string, neg: string): string | null =>
545
+ v > 0 ? pos : v < 0 ? neg : null;
546
+ let text: string | null = null;
547
+ switch (mod) {
548
+ case OBJ_MOD.STR: text = both("You feel stronger!", "You feel weaker!"); break;
549
+ case OBJ_MOD.INT: text = both("You feel smarter!", "You feel more stupid!"); break;
550
+ case OBJ_MOD.WIS: text = both("You feel wiser!", "You feel more naive!"); break;
551
+ case OBJ_MOD.DEX: text = both("You feel more dextrous!", "You feel clumsier!"); break;
552
+ case OBJ_MOD.CON: text = both("You feel healthier!", "You feel sicklier!"); break;
553
+ case OBJ_MOD.STEALTH: text = both("You feel stealthier.", "You feel noisier."); break;
554
+ case OBJ_MOD.SPEED: text = both("You feel strangely quick.", "You feel strangely sluggish."); break;
555
+ case OBJ_MOD.BLOWS: text = both("Your weapon tingles in your hands.", "Your weapon aches in your hands."); break;
556
+ case OBJ_MOD.SHOTS: text = both("Your missile weapon tingles in your hands.", "Your missile weapon aches in your hands."); break;
557
+ case OBJ_MOD.INFRA: text = "Your eyes tingle."; break;
558
+ case OBJ_MOD.LIGHT: text = "It glows!"; break;
559
+ default: break;
560
+ }
561
+ if (text) env.msg(text);
562
+ }
563
+
564
+ /**
565
+ * object_learn_on_wield (obj-knowledge.c L1820): learn the properties that
566
+ * become obvious the moment an item is worn or wielded - the obvious
567
+ * (OFID_WIELD) flags with sustains promoted to obvious on stat items, every
568
+ * modifier, and anything the item's curses supply. Guarded by the
569
+ * OBJ_NOTICE_WORN bit and marks flavored wearables tried.
570
+ *
571
+ * Without an env (worldless callers, e.g. unit tests that only exercise the
572
+ * calc_bonuses gate) only the modifier runes are learned, which is the whole
573
+ * real-play effect.
574
+ */
575
+ export function objectLearnOnWield(
576
+ player: Player,
577
+ obj: GameObject,
578
+ env?: RuneEnv,
579
+ ): void {
580
+ if (!env) {
581
+ const known = player.objKnown.modifiers;
582
+ for (let i = 0; i < OBJ_MOD_MAX; i++) {
583
+ if ((obj.modifiers[i] ?? 0) !== 0 && (known[i] ?? 0) === 0) known[i] = 1;
584
+ }
585
+ return;
586
+ }
587
+
588
+ /* Check the worn flag. */
589
+ if (obj.notice & OBJ_NOTICE.WORN) return;
590
+ obj.notice |= OBJ_NOTICE.WORN;
591
+
592
+ /* Worn means tried (for flavored wearables). */
593
+ env.flavor?.setTried(obj.kind);
594
+
595
+ /* The obvious object flags, plus sustains on items with a stat bonus. */
596
+ const obviousMask = objFlagMaskById(env, OFID.WIELD);
597
+ for (let i = 0; i < STAT_MAX; i++) {
598
+ if (obj.modifiers[i]) obviousMask.on(sustainFlag(i));
599
+ }
600
+
601
+ /* Learn about obvious, previously unknown flags. */
602
+ const oName = baseName(obj);
603
+ for (let flag = 1; flag < OF.MAX; flag++) {
604
+ if (!obj.flags.has(flag) || !obviousMask.has(flag)) continue;
605
+ if (!player.objKnown.flags.has(flag)) {
606
+ playerLearnFlagRune(player, env, flag);
607
+ /* p->upkeep->playing (obj-knowledge.c:1857). */
608
+ if (player.upkeep.playing) flagMessage(env, flag, oName);
609
+ }
610
+ }
611
+
612
+ /* Learn all modifiers. */
613
+ for (let i = 0; i < OBJ_MOD_MAX; i++) {
614
+ if ((obj.modifiers[i] ?? 0) !== 0 && !player.objKnown.modifiers[i]) {
615
+ playerLearnMod(player, env, i);
616
+ if (player.upkeep.playing) modMessage(env, obj, i);
617
+ }
618
+ }
619
+
620
+ /* Learn curses. */
621
+ objectCursesFindToA(player, env, obj);
622
+ objectCursesFindToH(player, env, obj);
623
+ objectCursesFindToD(player, env, obj);
624
+ objectCursesFindFlags(player, env, obj, obviousMask);
625
+ objectCursesFindModifiers(player, env, obj);
626
+ for (let i = 0; i < ELEM_MAX; i++) {
627
+ if (player.objKnown.elInfo[i]?.resLevel) {
628
+ objectCursesFindElement(player, env, obj, i);
629
+ }
630
+ }
631
+ }
632
+
633
+ /**
634
+ * missile_learn_on_ranged_attack: firing teaches the to-hit rune (when the
635
+ * missile or launcher is off-standard) and the to-dam rune.
636
+ */
637
+ export function missileLearnOnRangedAttack(
638
+ p: Player,
639
+ env: RuneEnv,
640
+ obj: GameObject,
641
+ ): void {
642
+ if (p.objKnown.toH && p.objKnown.toD) return;
643
+ if (!objectHasStandardToH(env, obj)) playerLearnCombat(p, env, "toH");
644
+ if (obj.toD) playerLearnCombat(p, env, "toD");
645
+ objectCursesFindToH(p, env, obj);
646
+ objectCursesFindToD(p, env, obj);
647
+ }
648
+
649
+ /* ------------------------------------------------------------------ *
650
+ * Learning from the equipment's behaviour.
651
+ * ------------------------------------------------------------------ */
652
+
653
+ /** equip_learn_on_defend: being hit teaches the to-armor rune. */
654
+ export function equipLearnOnDefend(p: Player, env: RuneEnv): void {
655
+ if (p.objKnown.toA) return;
656
+ for (let i = 0; i < p.body.count; i++) {
657
+ const obj = env.slotObject(i);
658
+ if (!obj) continue;
659
+ if (obj.toA) playerLearnCombat(p, env, "toA");
660
+ objectCursesFindToA(p, env, obj);
661
+ if (p.objKnown.toA) return;
662
+ }
663
+ /* Shape to_a: shapes are bound raw; DEFERRED with the shapechange system. */
664
+ }
665
+
666
+ function slotIndexByType(p: Player, type: string): number {
667
+ for (let i = 0; i < p.body.count; i++) {
668
+ if (p.body.slots[i]?.type === type) return i;
669
+ }
670
+ return -1;
671
+ }
672
+
673
+ /**
674
+ * equip_learn_on_ranged_attack: firing teaches the to-hit rune from any
675
+ * off-standard equipment except the weapon and launcher.
676
+ */
677
+ export function equipLearnOnRangedAttack(p: Player, env: RuneEnv): void {
678
+ if (p.objKnown.toH) return;
679
+ const weaponSlot = slotIndexByType(p, "WEAPON");
680
+ const bowSlot = slotIndexByType(p, "BOW");
681
+ for (let i = 0; i < p.body.count; i++) {
682
+ if (i === weaponSlot || i === bowSlot) continue;
683
+ const obj = env.slotObject(i);
684
+ if (!obj) continue;
685
+ if (!objectHasStandardToH(env, obj)) playerLearnCombat(p, env, "toH");
686
+ objectCursesFindToH(p, env, obj);
687
+ if (p.objKnown.toH) return;
688
+ }
689
+ }
690
+
691
+ /**
692
+ * equip_learn_on_melee_attack: attacking teaches the to-hit and to-dam runes
693
+ * from any off-standard equipment except the launcher.
694
+ */
695
+ export function equipLearnOnMeleeAttack(p: Player, env: RuneEnv): void {
696
+ if (p.objKnown.toH && p.objKnown.toD) return;
697
+ const bowSlot = slotIndexByType(p, "BOW");
698
+ for (let i = 0; i < p.body.count; i++) {
699
+ if (i === bowSlot) continue;
700
+ const obj = env.slotObject(i);
701
+ if (!obj) continue;
702
+ if (!objectHasStandardToH(env, obj)) playerLearnCombat(p, env, "toH");
703
+ if (obj.toD) playerLearnCombat(p, env, "toD");
704
+ objectCursesFindToH(p, env, obj);
705
+ objectCursesFindToD(p, env, obj);
706
+ if (p.objKnown.toH && p.objKnown.toD) return;
707
+ }
708
+ }
709
+
710
+ /**
711
+ * equip_learn_flag: a flag fired in play; learn its rune from any equipped
712
+ * item carrying it (with the flag_message), including via curses.
713
+ */
714
+ export function equipLearnFlag(p: Player, env: RuneEnv, flag: number): void {
715
+ if (!flag || flag < 0) return;
716
+ const mask = new FlagSet(OF_SIZE);
717
+ mask.on(flag);
718
+ for (let i = 0; i < p.body.count; i++) {
719
+ const obj = env.slotObject(i);
720
+ if (!obj) continue;
721
+ if (obj.flags.has(flag)) {
722
+ if (!p.objKnown.flags.has(flag)) {
723
+ flagMessage(env, flag, baseName(obj));
724
+ playerLearnFlagRune(p, env, flag);
725
+ }
726
+ }
727
+ /* obj->known "had a chance to display" marking: DEFERRED (display). */
728
+ objectCursesFindFlags(p, env, obj, mask);
729
+ }
730
+ }
731
+
732
+ /**
733
+ * equip_learn_element: an element hit the player; learn its rune from any
734
+ * equipped item affecting it (with the glow message), including via curses.
735
+ */
736
+ export function equipLearnElement(p: Player, env: RuneEnv, element: number): void {
737
+ if (element < 0 || element >= ELEM_MAX) return;
738
+ if ((p.objKnown.elInfo[element]?.resLevel ?? 0) === 1) return;
739
+ for (let i = 0; i < p.body.count; i++) {
740
+ const obj = env.slotObject(i);
741
+ if (!obj) continue;
742
+ if ((obj.elInfo[element]?.resLevel ?? 0) !== 0) {
743
+ if (p.upkeep.playing) env.msg?.(`Your ${baseName(obj)} glows.`);
744
+ playerLearnResist(p, env, element);
745
+ }
746
+ /* obj->known element marking: DEFERRED (display). */
747
+ objectCursesFindElement(p, env, obj, element);
748
+ }
749
+ }
750
+
751
+ /**
752
+ * shape_learn_on_assume (L1892): on taking a shape, learn its obvious
753
+ * (OFID_WIELD) flags and its resists, through the same equipment learn
754
+ * calls upstream uses.
755
+ */
756
+ export function shapeLearnOnAssume(
757
+ p: Player,
758
+ env: RuneEnv,
759
+ shape: import("../player/types.js").Shape,
760
+ ): void {
761
+ /* Get the shape's obvious flags. */
762
+ const f = shape.flags.clone();
763
+ f.inter(objFlagMaskById(env, OFID.WIELD));
764
+
765
+ /* Learn flags. */
766
+ for (let flag = f.next(FLAG_START); flag !== NO_FLAG; flag = f.next(flag + 1)) {
767
+ equipLearnFlag(p, env, flag);
768
+ }
769
+
770
+ /* Learn elements. */
771
+ for (let element = 0; element < ELEM_MAX; element++) {
772
+ if (
773
+ (shape.elInfo[element]?.resLevel ?? 0) !== 0 &&
774
+ (p.objKnown.elInfo[element]?.resLevel ?? 0) === 0
775
+ ) {
776
+ equipLearnElement(p, env, element);
777
+ }
778
+ }
779
+ }
780
+
781
+ /**
782
+ * equip_learn_after_time: learn the timed (OFID_TIMED) flags the equipment
783
+ * carries; called every 100 game turns from process_world.
784
+ */
785
+ export function equipLearnAfterTime(p: Player, env: RuneEnv): void {
786
+ const timedMask = objFlagMaskById(env, OFID.TIMED);
787
+ /* Drop already-known flags; bail if nothing is left to notice. */
788
+ let any = false;
789
+ for (let flag = 1; flag < OF.MAX; flag++) {
790
+ if (!timedMask.has(flag)) continue;
791
+ if (p.objKnown.flags.has(flag)) timedMask.off(flag);
792
+ else any = true;
793
+ }
794
+ if (!any) return;
795
+
796
+ for (let i = 0; i < p.body.count; i++) {
797
+ const obj = env.slotObject(i);
798
+ if (!obj) continue;
799
+ const oName = baseName(obj);
800
+ for (let flag = 1; flag < OF.MAX; flag++) {
801
+ if (!obj.flags.has(flag) || !timedMask.has(flag)) continue;
802
+ if (!p.objKnown.flags.has(flag)) flagMessage(env, flag, oName);
803
+ playerLearnFlagRune(p, env, flag);
804
+ }
805
+ objectCursesFindFlags(p, env, obj, timedMask);
806
+ }
807
+ }
808
+
809
+ /* ------------------------------------------------------------------ *
810
+ * Bulk learning.
811
+ * ------------------------------------------------------------------ */
812
+
813
+ /** player_learn_innate: know the racial element and flag runes at birth. */
814
+ export function playerLearnInnate(p: Player, env: RuneEnv): void {
815
+ for (let elem = 0; elem < ELEM_MAX; elem++) {
816
+ if ((p.race.elInfo[elem]?.resLevel ?? 0) !== 0) {
817
+ playerLearnResist(p, env, elem, false);
818
+ }
819
+ }
820
+ for (let flag = 1; flag < OF.MAX; flag++) {
821
+ if (p.race.flags.has(flag)) playerLearnFlagRune(p, env, flag, false);
822
+ }
823
+ }
824
+
825
+ /** player_learn_all_runes: learn absolutely everything (wizard mode). */
826
+ export function playerLearnAllRunes(p: Player, env: RuneEnv): void {
827
+ playerLearnCombat(p, env, "toA", false);
828
+ playerLearnCombat(p, env, "toH", false);
829
+ playerLearnCombat(p, env, "toD", false);
830
+ for (let i = 0; i < OBJ_MOD_MAX; i++) playerLearnMod(p, env, i, false);
831
+ for (let i = 0; i < ELEM_HIGH_MAX; i++) playerLearnResist(p, env, i, false);
832
+ for (let i = 1; i < OF.MAX; i++) playerLearnFlagRune(p, env, i, false);
833
+ for (let i = 1; i < env.brands.length; i++) playerLearnBrand(p, env, i, false);
834
+ for (let i = 1; i < env.slays.length; i++) playerLearnSlay(p, env, i, false);
835
+ for (let i = 1; i < env.curses.length; i++) playerLearnCurse(p, env, i, false);
836
+ }
837
+
838
+ /* ------------------------------------------------------------------ *
839
+ * The rune list (init_rune) and per-object rune enumeration. The port
840
+ * keeps player rune knowledge in typed stores (objKnown) instead of the
841
+ * upstream flat list, so the list here exists for the consumers that
842
+ * genuinely need enumeration order: EF_IDENTIFY's random unknown rune
843
+ * (upstream poss_runes fills in list order before randint0) and the later
844
+ * knowledge screens.
845
+ * ------------------------------------------------------------------ */
846
+
847
+ /** enum rune_variety. */
848
+ export type RuneVariety =
849
+ | "combat"
850
+ | "mod"
851
+ | "resist"
852
+ | "brand"
853
+ | "slay"
854
+ | "curse"
855
+ | "flag";
856
+
857
+ /** struct rune, resolved: a variety, its per-variety index, and a name. */
858
+ export interface Rune {
859
+ variety: RuneVariety;
860
+ index: number;
861
+ name: string;
862
+ }
863
+
864
+ /** COMBAT_RUNE_TO_A / TO_H / TO_D. */
865
+ const COMBAT_RUNE = ["toA", "toH", "toD"] as const;
866
+
867
+ /**
868
+ * init_rune: build the rune list in the exact upstream order - combat,
869
+ * modifiers, high elements, brands (first of each name), slays (first of
870
+ * each same-monsters group), named curses, then the identifiable flags
871
+ * (subtypes NONE / LIGHT / DIG / THROW / CURSE_ONLY excluded).
872
+ */
873
+ export function buildRuneList(env: RuneEnv): Rune[] {
874
+ const runes: Rune[] = [];
875
+ const combatNames = [
876
+ COMBAT_RUNE_NAMES.toA,
877
+ COMBAT_RUNE_NAMES.toH,
878
+ COMBAT_RUNE_NAMES.toD,
879
+ ];
880
+ for (let i = 0; i < 3; i++) {
881
+ runes.push({ variety: "combat", index: i, name: combatNames[i]! });
882
+ }
883
+ for (let i = 0; i < OBJ_MOD_MAX; i++) {
884
+ const name =
885
+ lookupProp(env, OBJ_PROPERTY.MOD, i)?.name ??
886
+ lookupProp(env, OBJ_PROPERTY.STAT, i)?.name ??
887
+ "";
888
+ runes.push({ variety: "mod", index: i, name });
889
+ }
890
+ for (let i = 0; i < ELEM_HIGH_MAX; i++) {
891
+ runes.push({ variety: "resist", index: i, name: env.elementNames[i] ?? "" });
892
+ }
893
+ for (let i = 1; i < env.brands.length; i++) {
894
+ const name = env.brands[i]?.name;
895
+ if (!name) continue;
896
+ let counted = false;
897
+ for (let j = 1; j < i; j++) {
898
+ if (env.brands[j]?.name === name) {
899
+ counted = true;
900
+ break;
901
+ }
902
+ }
903
+ if (!counted) runes.push({ variety: "brand", index: i, name });
904
+ }
905
+ for (let i = 1; i < env.slays.length; i++) {
906
+ const s = env.slays[i];
907
+ if (!s?.name) continue;
908
+ let counted = false;
909
+ for (let j = 1; j < i; j++) {
910
+ if (sameMonstersSlain(env.slays, i, j)) counted = true;
911
+ }
912
+ if (!counted) runes.push({ variety: "slay", index: i, name: s.name });
913
+ }
914
+ for (let i = 1; i < env.curses.length; i++) {
915
+ const name = env.curses[i]?.name;
916
+ if (name) runes.push({ variety: "curse", index: i, name });
917
+ }
918
+ for (let i = 1; i < OF.MAX; i++) {
919
+ const prop = lookupProp(env, OBJ_PROPERTY.FLAG, i);
920
+ if (!prop) continue;
921
+ if (
922
+ prop.subtype === OFT.NONE ||
923
+ prop.subtype === OFT.LIGHT ||
924
+ prop.subtype === OFT.DIG ||
925
+ prop.subtype === OFT.THROW ||
926
+ prop.subtype === OFT.CURSE_ONLY
927
+ ) {
928
+ continue;
929
+ }
930
+ runes.push({ variety: "flag", index: i, name: prop.name });
931
+ }
932
+ return runes;
933
+ }
934
+
935
+ /**
936
+ * rune_desc (obj-knowledge.c L344-403): the recall description of a rune. The
937
+ * text is computed per variety (no per-rune desc field in the data pack), so
938
+ * this ports the C switch verbatim. Combat runes have fixed strings keyed by
939
+ * COMBAT_RUNE_TO_A/H/D (obj-knowledge.h L35-37); curse runes read the curse's
940
+ * own desc (curses[index].desc) formatted as "Object %s."; every other variety
941
+ * substitutes the rune's name into its template. Returns "" for an out-of-range
942
+ * curse (the C default falls through to NULL).
943
+ */
944
+ export function runeDesc(env: RuneEnv, rune: Rune): string {
945
+ switch (rune.variety) {
946
+ case "combat":
947
+ if (rune.index === 0)
948
+ return "Object magically increases the player's armor class";
949
+ if (rune.index === 1)
950
+ return "Object magically increases the player's chance to hit";
951
+ if (rune.index === 2)
952
+ return "Object magically increases the player's damage";
953
+ return "";
954
+ case "mod":
955
+ return `Object gives the player a magical bonus to ${rune.name}.`;
956
+ case "resist":
957
+ return `Object affects the player's resistance to ${rune.name}.`;
958
+ case "brand":
959
+ return `Object brands the player's attacks with ${rune.name}.`;
960
+ case "slay":
961
+ return `Object makes the player's attacks against ${rune.name} more powerful.`;
962
+ case "curse": {
963
+ const desc = env.curses[rune.index]?.desc;
964
+ return desc ? `Object ${desc}.` : "";
965
+ }
966
+ case "flag":
967
+ return `Object gives the player the property of ${rune.name}.`;
968
+ }
969
+ }
970
+
971
+ /** player_knows_rune over the typed knowledge stores. */
972
+ export function playerKnowsRune(p: Player, rune: Rune): boolean {
973
+ switch (rune.variety) {
974
+ case "combat":
975
+ return !!p.objKnown[COMBAT_RUNE[rune.index] as "toA" | "toH" | "toD"];
976
+ case "mod":
977
+ return !!p.objKnown.modifiers[rune.index];
978
+ case "resist":
979
+ return !!p.objKnown.elInfo[rune.index]?.resLevel;
980
+ case "brand":
981
+ return playerKnowsBrand(p, rune.index);
982
+ case "slay":
983
+ return playerKnowsSlay(p, rune.index);
984
+ case "curse":
985
+ return playerKnowsCurse(p, rune.index);
986
+ case "flag":
987
+ return p.objKnown.flags.has(rune.index);
988
+ }
989
+ }
990
+
991
+ /** object_has_rune. */
992
+ export function objectHasRune(
993
+ env: RuneEnv,
994
+ obj: GameObject,
995
+ rune: Rune,
996
+ ): boolean {
997
+ switch (rune.variety) {
998
+ case "combat":
999
+ if (rune.index === 0) return obj.toA !== 0;
1000
+ if (rune.index === 1) return !objectHasStandardToH(env, obj);
1001
+ return obj.toD !== 0;
1002
+ case "mod":
1003
+ return (obj.modifiers[rune.index] ?? 0) !== 0;
1004
+ case "resist":
1005
+ return (obj.elInfo[rune.index]?.resLevel ?? 0) !== 0;
1006
+ case "brand": {
1007
+ if (!obj.brands) return false;
1008
+ for (let i = 0; i < obj.brands.length; i++) {
1009
+ if (obj.brands[i] && env.brands[i]?.name === rune.name) return true;
1010
+ }
1011
+ return false;
1012
+ }
1013
+ case "slay": {
1014
+ if (!obj.slays) return false;
1015
+ for (let i = 0; i < obj.slays.length; i++) {
1016
+ if (obj.slays[i] && sameMonstersSlain(env.slays, rune.index, i)) {
1017
+ return true;
1018
+ }
1019
+ }
1020
+ return false;
1021
+ }
1022
+ case "curse":
1023
+ return (obj.curses?.[rune.index]?.power ?? 0) !== 0;
1024
+ case "flag":
1025
+ return obj.flags.has(rune.index);
1026
+ }
1027
+ }
1028
+
1029
+ /**
1030
+ * object_runes_known, reduced to the port's player-rune knowledge model:
1031
+ * every rune the object carries is known to the player. (Upstream compares
1032
+ * the obj->known twin, which is filled from the same rune knowledge.)
1033
+ */
1034
+ export function objectRunesKnown(
1035
+ p: Player,
1036
+ env: RuneEnv,
1037
+ obj: GameObject,
1038
+ runes: readonly Rune[],
1039
+ ): boolean {
1040
+ for (const rune of runes) {
1041
+ if (objectHasRune(env, obj, rune) && !playerKnowsRune(p, rune)) {
1042
+ return false;
1043
+ }
1044
+ }
1045
+ return true;
1046
+ }
1047
+
1048
+ /** player_learn_rune dispatched by variety. */
1049
+ export function playerLearnRune(
1050
+ p: Player,
1051
+ env: RuneEnv,
1052
+ rune: Rune,
1053
+ message: boolean,
1054
+ ): boolean {
1055
+ switch (rune.variety) {
1056
+ case "combat":
1057
+ return playerLearnCombat(
1058
+ p,
1059
+ env,
1060
+ COMBAT_RUNE[rune.index] as "toA" | "toH" | "toD",
1061
+ message,
1062
+ );
1063
+ case "mod":
1064
+ return playerLearnMod(p, env, rune.index, message);
1065
+ case "resist":
1066
+ return playerLearnResist(p, env, rune.index, message);
1067
+ case "brand":
1068
+ return playerLearnBrand(p, env, rune.index, message);
1069
+ case "slay":
1070
+ return playerLearnSlay(p, env, rune.index, message);
1071
+ case "curse":
1072
+ return playerLearnCurse(p, env, rune.index, message);
1073
+ case "flag":
1074
+ return playerLearnFlagRune(p, env, rune.index, message);
1075
+ }
1076
+ }
1077
+
1078
+ /**
1079
+ * object_find_unknown_rune: a random unknown rune carried by the object
1080
+ * (upstream RNG: candidates gathered in list order, then randint0), or -1.
1081
+ */
1082
+ export function objectFindUnknownRune(
1083
+ rng: { randint0(m: number): number },
1084
+ p: Player,
1085
+ env: RuneEnv,
1086
+ obj: GameObject,
1087
+ runes: readonly Rune[],
1088
+ ): number {
1089
+ if (objectRunesKnown(p, env, obj, runes)) return -1;
1090
+ const poss: number[] = [];
1091
+ for (let i = 0; i < runes.length; i++) {
1092
+ if (objectHasRune(env, obj, runes[i]!) && !playerKnowsRune(p, runes[i]!)) {
1093
+ poss.push(i);
1094
+ }
1095
+ }
1096
+ if (poss.length === 0) return -1;
1097
+ return poss[rng.randint0(poss.length)]!;
1098
+ }
1099
+
1100
+ /**
1101
+ * object_learn_unknown_rune (obj-knowledge.c L1798): learn a random unknown
1102
+ * rune from the object; with none left the object is marked assessed. Returns
1103
+ * whether a rune was learned.
1104
+ *
1105
+ * Upstream both branches end in player_know_object (directly at L1806, or via
1106
+ * player_learn_rune -> update_player_object_knowledge at L1811), which fires the
1107
+ * object_flavor_aware side effect for the object. The port synthesises the
1108
+ * known shadow on demand for display, so that awareness half is fired here (a
1109
+ * knowledge-UPDATE site) via playerKnowObjectAwareness. `flavor` is optional so
1110
+ * callers with no flavor environment (older tests) keep the bare rune-learn.
1111
+ */
1112
+ export function objectLearnUnknownRune(
1113
+ rng: { randint0(m: number): number },
1114
+ p: Player,
1115
+ env: RuneEnv,
1116
+ obj: GameObject,
1117
+ runes: readonly Rune[],
1118
+ flavor?: FlavorKnowledge,
1119
+ flavorDeps: FlavorAwareDeps = NOOP_FLAVOR_AWARE_DEPS,
1120
+ ): boolean {
1121
+ const i = objectFindUnknownRune(rng, p, env, obj, runes);
1122
+ let learned: boolean;
1123
+ if (i < 0) {
1124
+ /* No unknown runes: assessed (player_know_object rides the known
1125
+ * twin, which the port's rune model replaces). */
1126
+ obj.notice |= OBJ_NOTICE.ASSESSED;
1127
+ learned = false;
1128
+ } else {
1129
+ learned = playerLearnRune(p, env, runes[i]!, true);
1130
+ }
1131
+ /* player_know_object's awareness side effect (L1163-1175), fired for this
1132
+ * object at the knowledge-update site (never in the display-only shadow). */
1133
+ if (flavor) playerKnowObjectAwareness(p, env, obj, runes, flavor, flavorDeps);
1134
+ return learned;
1135
+ }
1136
+
1137
+ /**
1138
+ * Flavor awareness, ported from the kind->aware / kind->tried bits of
1139
+ * reference/src/object.h and the accessors/setters in obj-knowledge.c
1140
+ * (object_flavor_is_aware L2243, object_flavor_was_tried L2254,
1141
+ * object_flavor_aware L2266, object_flavor_tried L2320).
1142
+ *
1143
+ * Upstream these two bits live on the shared object_kind template and are
1144
+ * global to the running game. This port keeps them out of the immutable bound
1145
+ * registry and in a per-game FlavorKnowledge, keyed by kind index (kidx), so a
1146
+ * bound ObjRegistry stays reusable across games.
1147
+ *
1148
+ * "aware" means the player knows what a flavored kind does (has quaffed the
1149
+ * potion, etc.); "tried" means a kind of that flavor has been used without the
1150
+ * effect being learned. object_value and object_value_base read is_aware to
1151
+ * decide between the real cost and a flat per-tval guess.
1152
+ */
1153
+ /**
1154
+ * The player-side side effects object_flavor_aware fires beyond flipping the
1155
+ * aware bit (obj-knowledge.c L2276-2279). Injected so FlavorKnowledge stays
1156
+ * decoupled from the ignore subsystem (obj/ignore.ts IgnoreSettings) and the
1157
+ * player's upkeep, mirroring how the rest of the port threads deps. The
1158
+ * gear/store base_known sweep and floor re-light are NOT here: the former is
1159
+ * covered by the on-demand known shadow, the latter is a display concern (see
1160
+ * FlavorKnowledge.objectFlavorAware).
1161
+ */
1162
+ export interface FlavorAwareDeps {
1163
+ /** kind_is_ignored_unaware(kind) (obj-ignore.c): ignored while unidentified? */
1164
+ isIgnoredUnaware(kidx: number): boolean;
1165
+ /** kind_ignore_when_aware(kind) (obj-ignore.c): carry the ignore bit over. */
1166
+ ignoreWhenAware(kidx: number): void;
1167
+ /** p->upkeep->notice |= PN_IGNORE: request an ignore re-check of the pack. */
1168
+ requestIgnoreNotice(): void;
1169
+ }
1170
+
1171
+ /**
1172
+ * An inert FlavorAwareDeps for callers that have a FlavorKnowledge but no
1173
+ * live ignore/notice environment (birth-time scripting, tests, or a caller
1174
+ * that intentionally wants the bare aware-bit flip with none of the L2276-79
1175
+ * side effects). Equivalent to the old bare setAware() call.
1176
+ */
1177
+ export const NOOP_FLAVOR_AWARE_DEPS: FlavorAwareDeps = {
1178
+ isIgnoredUnaware: () => false,
1179
+ ignoreWhenAware: () => {},
1180
+ requestIgnoreNotice: () => {},
1181
+ };
1182
+
1183
+ export class FlavorKnowledge {
1184
+ private readonly awareKidx = new Set<number>();
1185
+ private readonly triedKidx = new Set<number>();
1186
+
1187
+ /**
1188
+ * @param ordinaryKindCount z_info->ordinary_kind_max: kinds at or above this
1189
+ * index are INSTA_ART dummies and are never marked tried.
1190
+ */
1191
+ constructor(private readonly ordinaryKindCount: number) {}
1192
+
1193
+ /**
1194
+ * z_info->ordinary_kind_max: kinds at or above this index are special-artifact
1195
+ * dummies (see obj-knowledge.c L1168's kidx >= ordinary_kind_max test).
1196
+ */
1197
+ get ordinaryKindMax(): number {
1198
+ return this.ordinaryKindCount;
1199
+ }
1200
+
1201
+ /** object_flavor_is_aware(obj): is the player aware of this kind's flavor? */
1202
+ isAware(kind: ObjectKind): boolean {
1203
+ return this.awareKidx.has(kind.kidx);
1204
+ }
1205
+
1206
+ /** object_flavor_was_tried(obj): has a kind of this flavor been tried? */
1207
+ wasTried(kind: ObjectKind): boolean {
1208
+ return this.triedKidx.has(kind.kidx);
1209
+ }
1210
+
1211
+ /**
1212
+ * The aware-bit half of object_flavor_aware (L2272-2273): mark a kind's
1213
+ * flavor known; returns true when this made a change. This is the pure
1214
+ * primitive - it flips the bit and nothing else, so it is safe for birth
1215
+ * aware-marking (flavor.ts) and savefile restore, which must NOT trigger the
1216
+ * ignore re-check. Callers that are the player becoming aware in play should
1217
+ * use objectFlavorAware() below, which layers on the awareness side effects.
1218
+ */
1219
+ setAware(kind: ObjectKind): boolean {
1220
+ if (this.awareKidx.has(kind.kidx)) return false;
1221
+ this.awareKidx.add(kind.kidx);
1222
+ return true;
1223
+ }
1224
+
1225
+ /**
1226
+ * object_flavor_aware (obj-knowledge.c L2266): the player becomes aware of a
1227
+ * flavoured kind AND the awareness side effects fire. Returns true when
1228
+ * awareness newly changed (upstream is void; the port surfaces the change so
1229
+ * callers can gate a message / redraw).
1230
+ *
1231
+ * What each upstream step maps to in the port's on-demand-shadow model:
1232
+ * - kind->aware = true (L2272-2273): setAware below.
1233
+ * - obj->known->effect = obj->effect (L2274): the port keeps NO persistent
1234
+ * obj->known twin; the known shadow is synthesised on demand and
1235
+ * objectSetBaseKnown (known-object.ts L157-170) already fills shadow.effect
1236
+ * from deps.isAware(kind). Once the bit above flips, every later synthesis
1237
+ * reveals the effect automatically - there is nothing to write here.
1238
+ * - ignore/autoinscribe fix (L2276-2279): ported below via `deps`.
1239
+ * - object_set_base_known over p->gear and every store's stock (L2281-2290):
1240
+ * a NO-OP in the port. Those are exactly the twins that are synthesised on
1241
+ * demand and re-read the freshly-flipped aware bit, so there is no stored
1242
+ * copy to re-sweep. (Building a persistent twin to sweep is the separate
1243
+ * DEFERRED obj->known item, out of scope here.)
1244
+ * - floor-tile re-light for kinds that change glyph on awareness
1245
+ * (L2293-2312): a cave/display concern, outside packages/core/src/obj.
1246
+ *
1247
+ * @returns true iff the kind was not already aware.
1248
+ */
1249
+ objectFlavorAware(kind: ObjectKind, deps: FlavorAwareDeps): boolean {
1250
+ /* if (obj->kind->aware) return; obj->kind->aware = true; (L2272-2273). The
1251
+ * obj->known->effect reveal (L2274) is covered by the on-demand shadow. */
1252
+ if (!this.setAware(kind)) return false;
1253
+
1254
+ /* Fix ignore/autoinscribe (L2276-2279): an item ignored while unaware keeps
1255
+ * being ignored now that it is aware, then flag an ignore re-check. */
1256
+ if (deps.isIgnoredUnaware(kind.kidx)) deps.ignoreWhenAware(kind.kidx);
1257
+ deps.requestIgnoreNotice();
1258
+
1259
+ /* Gear/store base_known sweep (L2281-2290) and floor re-light (L2293-2312)
1260
+ * are on-demand-covered / display-layer respectively; see the doc above. */
1261
+ return true;
1262
+ }
1263
+
1264
+ /** object_flavor_tried (L2320): mark a kind tried; artifacts are skipped. */
1265
+ setTried(kind: ObjectKind): void {
1266
+ if (kind.kidx >= this.ordinaryKindCount) return;
1267
+ this.triedKidx.add(kind.kidx);
1268
+ }
1269
+
1270
+ /** A JSON-safe snapshot of the aware/tried kidx sets, for savefiles. */
1271
+ snapshot(): { aware: number[]; tried: number[] } {
1272
+ return {
1273
+ aware: Array.from(this.awareKidx),
1274
+ tried: Array.from(this.triedKidx),
1275
+ };
1276
+ }
1277
+
1278
+ /** Restore a snapshot() payload (replacing the current knowledge). */
1279
+ restore(data: { aware: number[]; tried: number[] }): void {
1280
+ this.awareKidx.clear();
1281
+ this.triedKidx.clear();
1282
+ for (const k of data.aware) this.awareKidx.add(k);
1283
+ for (const k of data.tried) this.triedKidx.add(k);
1284
+ }
1285
+ }
1286
+
1287
+ /**
1288
+ * The per-game "everseen" knowledge (object.h struct object_kind.everseen and
1289
+ * struct ego_item.everseen). Upstream these bits live on the shared kind/ego
1290
+ * templates and are global to the running game; this port keeps them out of the
1291
+ * immutable bound registry - exactly like FlavorKnowledge - in a per-game store
1292
+ * keyed by kind index (kidx) and ego index (eidx), so a bound ObjRegistry stays
1293
+ * reusable across games and the flags ride the save (save.c L397, L533).
1294
+ *
1295
+ * A kind or ego is marked everseen the first time the player sees an item whose
1296
+ * name they know: object_desc sets obj->kind->everseen once the flavour is
1297
+ * aware, and obj->ego->everseen once the ego is identified (obj-desc.c
1298
+ * L633-637), plus player-birth.c L658 marks each bought start-item's kind. The
1299
+ * object-knowledge browser lists a kind when it is everseen OR flavoured
1300
+ * (ui-knowledge.c L2157); the ego browser lists an ego when it is everseen
1301
+ * (L1847).
1302
+ *
1303
+ * Marking is a pure Set insert: it draws no RNG and does not depend on draw
1304
+ * order, so wiring it into object_desc/generation cannot perturb determinism.
1305
+ */
1306
+ export class EverseenKnowledge {
1307
+ private readonly seenKidx = new Set<number>();
1308
+ private readonly seenEidx = new Set<number>();
1309
+
1310
+ /** obj->kind->everseen: has the player ever seen this kind (name known)? */
1311
+ kindSeen(kind: ObjectKind): boolean {
1312
+ return this.seenKidx.has(kind.kidx);
1313
+ }
1314
+
1315
+ /** obj->ego->everseen: has the player ever seen this ego (identified)? */
1316
+ egoSeen(ego: EgoItem): boolean {
1317
+ return this.seenEidx.has(ego.eidx);
1318
+ }
1319
+
1320
+ /** obj->kind->everseen = true (obj-desc.c L637 / player-birth.c L658). */
1321
+ markKind(kind: ObjectKind): void {
1322
+ this.seenKidx.add(kind.kidx);
1323
+ }
1324
+
1325
+ /** obj->ego->everseen = true (obj-desc.c L634). */
1326
+ markEgo(ego: EgoItem): void {
1327
+ this.seenEidx.add(ego.eidx);
1328
+ }
1329
+
1330
+ /** A JSON-safe snapshot of the seen kidx/eidx sets, for savefiles. */
1331
+ snapshot(): { kinds: number[]; egos: number[] } {
1332
+ return {
1333
+ kinds: Array.from(this.seenKidx),
1334
+ egos: Array.from(this.seenEidx),
1335
+ };
1336
+ }
1337
+
1338
+ /** Restore a snapshot() payload (replacing the current knowledge). */
1339
+ restore(data: { kinds: number[]; egos: number[] }): void {
1340
+ this.seenKidx.clear();
1341
+ this.seenEidx.clear();
1342
+ for (const k of data.kinds) this.seenKidx.add(k);
1343
+ for (const e of data.egos) this.seenEidx.add(e);
1344
+ }
1345
+ }
1346
+
1347
+ /**
1348
+ * The per-kind autoinscription registry (object.h L241-242's
1349
+ * kind->note_aware / kind->note_unaware). Upstream these two quark strings
1350
+ * live on the shared object_kind template and are global to the running game;
1351
+ * this port keeps them out of the immutable bound registry - like
1352
+ * FlavorKnowledge and IgnoreSettings - in a per-game store keyed by kind index
1353
+ * (kidx), so a bound ObjRegistry stays reusable across games and the notes ride
1354
+ * the save.
1355
+ *
1356
+ * get(kidx, aware) is get_autoinscription (obj-ignore.c L229): the aware note
1357
+ * when the kind is aware, else the unaware note. set() is
1358
+ * add_autoinscription / remove_autoinscription (obj-ignore.c L322 / L294): a
1359
+ * non-empty note registers that slot, an empty note clears it (upstream's
1360
+ * NULL-inscription -> remove_autoinscription path).
1361
+ *
1362
+ * This is the KIND-note half only. The separate rune-based autoinscription
1363
+ * (runes_autoinscribe, obj-ignore.c L217) rides the rune-knowledge system and
1364
+ * stays ledger-deferred (#24).
1365
+ */
1366
+ export class AutoinscriptionRegistry {
1367
+ /** kind->note_aware / note_unaware, keyed by kidx. Absent slot == no note. */
1368
+ private readonly notes = new Map<number, { aware?: string; unaware?: string }>();
1369
+
1370
+ /** get_autoinscription(kind, aware) (obj-ignore.c L229). */
1371
+ get(kidx: number, aware: boolean): string | undefined {
1372
+ const rec = this.notes.get(kidx);
1373
+ if (!rec) return undefined;
1374
+ return aware ? rec.aware : rec.unaware;
1375
+ }
1376
+
1377
+ /**
1378
+ * add_autoinscription (obj-ignore.c L322) / remove_autoinscription (L294):
1379
+ * register the aware or unaware note for a kind. An empty note clears that
1380
+ * slot (upstream's null-inscription branch); a kind with neither slot set is
1381
+ * dropped from the map entirely.
1382
+ */
1383
+ set(kidx: number, note: string, aware: boolean): void {
1384
+ const rec = this.notes.get(kidx) ?? {};
1385
+ if (note.length > 0) {
1386
+ if (aware) rec.aware = note;
1387
+ else rec.unaware = note;
1388
+ } else if (aware) {
1389
+ delete rec.aware;
1390
+ } else {
1391
+ delete rec.unaware;
1392
+ }
1393
+ if (rec.aware === undefined && rec.unaware === undefined) {
1394
+ this.notes.delete(kidx);
1395
+ } else {
1396
+ this.notes.set(kidx, rec);
1397
+ }
1398
+ }
1399
+
1400
+ /** remove_autoinscription (obj-ignore.c L294): clear both slots for a kind. */
1401
+ clear(kidx: number): void {
1402
+ this.notes.delete(kidx);
1403
+ }
1404
+
1405
+ /** Every kind with a registered note (either slot), for the management UI. */
1406
+ entries(): Array<[number, { aware?: string; unaware?: string }]> {
1407
+ return Array.from(this.notes.entries()).map(([kidx, rec]) => [
1408
+ kidx,
1409
+ { ...rec },
1410
+ ]);
1411
+ }
1412
+ }
1413
+
1414
+ /**
1415
+ * rune_list[i].note (object.h struct rune): the player's per-rune
1416
+ * autoinscription. Upstream this is a quark on the file-static rune_list, set
1417
+ * from the rune knowledge screen (ui-knowledge.c rune_xtra_act, L2246-2280) and
1418
+ * saved/loaded by wr_ignore (save.c:586-605) / rd_ignore (load.c:937-945).
1419
+ * Like AutoinscriptionRegistry it lives per-game here so the bound registries
1420
+ * stay immutable, keyed by the rune's index in buildRuneList - the same key
1421
+ * upstream uses to address rune_list at runtime. (The SAVEFILE keys by runeKey
1422
+ * instead; see runeKey below for why.)
1423
+ *
1424
+ * WART preserved: upstream `rune_set_note(i, "")` goes through quark_add(""),
1425
+ * which returns a NONZERO quark (z-quark.c:31-49 never returns 0 for a new
1426
+ * string), so an empty inscription is a LIVE note that appends nothing - it is
1427
+ * written to the savefile and shows the '}' uninscribe prompt. Only
1428
+ * rune_set_note(i, NULL) clears the slot. Hence set(i, "") stores, set(i, null)
1429
+ * deletes.
1430
+ */
1431
+ export class RuneNoteRegistry {
1432
+ private readonly notes = new Map<number, string>();
1433
+
1434
+ /** rune_note(i) (obj-knowledge.c:406). undefined == quark 0 == no note. */
1435
+ get(i: number): string | undefined {
1436
+ return this.notes.get(i);
1437
+ }
1438
+
1439
+ /** rune_set_note(i, inscription) (obj-knowledge.c:414). */
1440
+ set(i: number, note: string | null): void {
1441
+ if (note === null) this.notes.delete(i);
1442
+ else this.notes.set(i, note);
1443
+ }
1444
+
1445
+ /** Every rune index carrying a note, for the save block and the UI. */
1446
+ entries(): Array<[number, string]> {
1447
+ return Array.from(this.notes.entries());
1448
+ }
1449
+ }
1450
+
1451
+ /** rune_note (obj-knowledge.c:406) as a free function over the registry. */
1452
+ export function runeNote(
1453
+ registry: RuneNoteRegistry,
1454
+ i: number,
1455
+ ): string | undefined {
1456
+ return registry.get(i);
1457
+ }
1458
+
1459
+ /** rune_set_note (obj-knowledge.c:414) as a free function over the registry. */
1460
+ export function runeSetNote(
1461
+ registry: RuneNoteRegistry,
1462
+ i: number,
1463
+ note: string | null,
1464
+ ): void {
1465
+ registry.set(i, note);
1466
+ }
1467
+
1468
+ /**
1469
+ * A pack-stable identity for a rune, for the savefile only.
1470
+ *
1471
+ * Upstream writes the raw rune-list index (`wr_s16b(k)`, save.c:600) and reads
1472
+ * it straight back (`rune_set_note(runeid, tmp)`, load.c:944), which mis-targets
1473
+ * if the loaded data changes the rune list's shape - the same positional-index
1474
+ * fragility wr_object_memory has. That fragility is a property of the C
1475
+ * SAVEFILE FORMAT, and the port's format is the ratified JSON document whose
1476
+ * load-bearing rule is that every content reference is a stable id
1477
+ * (MOD_LIFECYCLE decision 1, session/save.ts SAVE_VERSION). Runtime behaviour
1478
+ * is untouched: in play a rune is still addressed by its buildRuneList index,
1479
+ * exactly as upstream addresses rune_list.
1480
+ *
1481
+ * `variety:name` is unique across the whole list: buildRuneList already
1482
+ * de-duplicates brands and slays by name, and the remaining varieties draw one
1483
+ * rune per distinct property name.
1484
+ */
1485
+ export function runeKey(rune: Rune): string {
1486
+ return `${rune.variety}:${rune.name}`;
1487
+ }
1488
+
1489
+ /**
1490
+ * rune_name (obj-knowledge.c:325): the display name of a rune, with the
1491
+ * variety-specific decoration - "<x> brand", "slay <x>", "<x> curse",
1492
+ * "resist <x>", and the bare name for combat / modifier / flag runes.
1493
+ */
1494
+ export function runeName(rune: Rune): string {
1495
+ switch (rune.variety) {
1496
+ case "brand":
1497
+ return `${rune.name} brand`;
1498
+ case "slay":
1499
+ return `slay ${rune.name}`;
1500
+ case "curse":
1501
+ return `${rune.name} curse`;
1502
+ case "resist":
1503
+ return `resist ${rune.name}`;
1504
+ default:
1505
+ return rune.name;
1506
+ }
1507
+ }
1508
+
1509
+ /**
1510
+ * get_autoinscription (obj-ignore.c L229) as a free function over the registry,
1511
+ * mirroring the upstream signature: the aware note when the kind is aware, else
1512
+ * the unaware note; undefined when the kind has no note for that awareness.
1513
+ */
1514
+ export function getAutoinscription(
1515
+ registry: AutoinscriptionRegistry,
1516
+ kidx: number,
1517
+ aware: boolean,
1518
+ ): string | undefined {
1519
+ return registry.get(kidx, aware);
1520
+ }
1521
+
1522
+ /**
1523
+ * add_autoinscription / remove_autoinscription (obj-ignore.c L322 / L294) as a
1524
+ * free function over the registry: register `note` for the aware or unaware
1525
+ * slot; an empty note clears it.
1526
+ */
1527
+ export function setAutoinscription(
1528
+ registry: AutoinscriptionRegistry,
1529
+ kidx: number,
1530
+ note: string,
1531
+ aware: boolean,
1532
+ ): void {
1533
+ registry.set(kidx, note, aware);
1534
+ }
1535
+
1536
+ /**
1537
+ * The object_flavor_aware side effect of player_know_object (obj-knowledge.c
1538
+ * L1163-1175). This is the awareness-UPDATE half of player_know_object, split
1539
+ * out so it can be fired at the port's knowledge-update sites - upstream the
1540
+ * whole of player_know_object writes the obj->known twin AND fires this; the
1541
+ * port synthesises the twin on demand for display, so ONLY this awareness half
1542
+ * needs a home, and it must never live on the display path (describing an item
1543
+ * must not mutate the player's knowledge).
1544
+ *
1545
+ * player_know_object early-returns for a not-yet-assessed object (L1033) before
1546
+ * ever reaching these branches, so this mirrors that gate: awareness fires only
1547
+ * once the object is ASSESSED. Then:
1548
+ * - jewellery whose non-curse runes are all known becomes aware (L1163-1167);
1549
+ * - a special artifact that isn't jewellery (kidx >= ordinary_kind_max) becomes
1550
+ * aware outright (L1168-1175).
1551
+ *
1552
+ * object_flavor_aware itself early-returns when the kind is already aware, so
1553
+ * re-firing across repeated rune-learns is a no-op.
1554
+ */
1555
+ export function playerKnowObjectAwareness(
1556
+ p: Player,
1557
+ env: RuneEnv,
1558
+ obj: GameObject,
1559
+ runes: readonly Rune[],
1560
+ flavor: FlavorKnowledge,
1561
+ flavorDeps: FlavorAwareDeps,
1562
+ ): void {
1563
+ /* player_know_object's early return at L1033: no awareness for the unassessed. */
1564
+ if ((obj.notice & OBJ_NOTICE.ASSESSED) === 0) return;
1565
+
1566
+ if (tvalIsJewelry(obj.tval)) {
1567
+ /* object_non_curse_runes_known(obj) (L678): every non-curse rune the object
1568
+ * carries is known to the player. */
1569
+ const nonCurse = runes.filter((r) => r.variety !== "curse");
1570
+ if (objectRunesKnown(p, env, obj, nonCurse)) {
1571
+ flavor.objectFlavorAware(obj.kind, flavorDeps); // L1166
1572
+ }
1573
+ } else if (obj.kind.kidx >= flavor.ordinaryKindMax) {
1574
+ /* Special artifact that isn't jewelry (L1168-1175). */
1575
+ flavor.objectFlavorAware(obj.kind, flavorDeps); // L1174
1576
+ }
1577
+ }