@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,2213 @@
1
+ /**
2
+ * Room builders and the runtime-registrable room-builder registry, ported
3
+ * from reference/src/gen-room.c (Angband 4.2.6).
4
+ *
5
+ * MODDABILITY (ratified pillar, decision 13): builders live in a string-keyed
6
+ * RoomRegistry. createRoomRegistry() populates it with the upstream builders;
7
+ * a mod can register a new builder under any key and reference it from a
8
+ * (modded) dungeon profile's room list. There is no closed switch.
9
+ *
10
+ * PORTED (faithful geometry and RNG order for the structural work): staircase
11
+ * (persistent-only), simple, circular, overlap, crossed, large, template
12
+ * (build_room_template from room_template.json), vault (build_vault from
13
+ * vault.json) and the vault-type wrappers (lesser/medium/greater and their
14
+ * "(new)" variants, interesting).
15
+ *
16
+ * SIMPLIFIED (ledgered in parity/ledger/gen-rooms.yaml): nest and pit build the
17
+ * faithful room shell but fill with any depth-appropriate monster instead of a
18
+ * themed pit profile; vault racial glyphs likewise place any depth-appropriate
19
+ * monster rather than a base-symbol-restricted one.
20
+ *
21
+ * PORTED (starburst + cellular builders): moria (build_moria), room_of_chambers
22
+ * (build_room_of_chambers, with make_chamber/hollow_out_room carving and the
23
+ * get_chamber_monsters themed fill) and huge (build_huge). Faithful RNG order.
24
+ */
25
+
26
+ import { FEAT, ORIGIN, SQUARE } from "../generated/index.js";
27
+ import type { Loc } from "../loc.js";
28
+ import { loc, DDGRID_DDD } from "../loc.js";
29
+ import type { Rng } from "../rng.js";
30
+ import { tvalFindIdx } from "../obj/bind.js";
31
+ import type { Chunk } from "../world/chunk.js";
32
+ import type { Gen } from "./util.js";
33
+ import {
34
+ countNeighbors,
35
+ drawRectangle,
36
+ fillCircle,
37
+ fillRectangle,
38
+ generateHole,
39
+ generateMark,
40
+ generateOpen,
41
+ generatePlus,
42
+ generateRoom,
43
+ generateStarburstRoom,
44
+ locDiff,
45
+ locSum,
46
+ pickAndPlaceMonster,
47
+ placeClosedDoor,
48
+ placeNewMonster,
49
+ placeObject,
50
+ placeGold,
51
+ placeRandomDoor,
52
+ placeRandomStairs,
53
+ placeSecretDoor,
54
+ placeTrap,
55
+ randDir,
56
+ setBorderingWalls,
57
+ setMarkedGranite,
58
+ squareIsRoom,
59
+ vaultMonsters,
60
+ vaultObjects,
61
+ vaultTraps,
62
+ } from "./util.js";
63
+ import { getChamberMonsters, getVaultMonsters, monPitHook, setPitType } from "./gen-monster.js";
64
+ import type { MonsterGroupInfo } from "../mon/monster.js";
65
+ import type { MonsterRace } from "../mon/types.js";
66
+ import { MON_GROUP } from "../mon/types.js";
67
+
68
+ /* ------------------------------------------------------------------ *
69
+ * Room and vault template data.
70
+ * ------------------------------------------------------------------ */
71
+
72
+ /** room_template.json record. */
73
+ export interface RoomTemplateRecordJson {
74
+ name: string;
75
+ type: number;
76
+ rating: number;
77
+ rows: number;
78
+ columns: number;
79
+ doors: number;
80
+ tval: string;
81
+ D: string[];
82
+ flags?: string[];
83
+ }
84
+
85
+ /** vault.json record. */
86
+ export interface VaultRecordJson {
87
+ name: string;
88
+ type: string;
89
+ rating: number;
90
+ rows: number;
91
+ columns: number;
92
+ "min-depth"?: number;
93
+ "max-depth"?: number;
94
+ D: string[];
95
+ flags?: string[];
96
+ }
97
+
98
+ export interface RoomTemplate {
99
+ name: string;
100
+ typ: number;
101
+ rat: number;
102
+ hgt: number;
103
+ wid: number;
104
+ dor: number;
105
+ tval: number;
106
+ rows: string[];
107
+ fewEntrances: boolean;
108
+ }
109
+
110
+ export interface Vault {
111
+ name: string;
112
+ typ: string;
113
+ rat: number;
114
+ hgt: number;
115
+ wid: number;
116
+ minLev: number;
117
+ maxLev: number;
118
+ rows: string[];
119
+ fewEntrances: boolean;
120
+ }
121
+
122
+ function hasFewEntrances(flags: string[] | undefined): boolean {
123
+ return !!flags && flags.some((f) => f.split("|").some((n) => n.trim() === "FEW_ENTRANCES"));
124
+ }
125
+
126
+ /** Load room templates from parsed room_template.json records. */
127
+ export function loadRoomTemplates(records: RoomTemplateRecordJson[]): RoomTemplate[] {
128
+ return [...records].reverse().map((r) => ({
129
+ name: r.name,
130
+ typ: r.type,
131
+ rat: r.rating,
132
+ hgt: r.rows,
133
+ wid: r.columns,
134
+ dor: r.doors,
135
+ tval: r.tval === "0" ? 0 : tvalFindIdx(r.tval),
136
+ rows: [...r.D],
137
+ fewEntrances: hasFewEntrances(r.flags),
138
+ }));
139
+ }
140
+
141
+ /**
142
+ * Load vaults from parsed vault.json records - the port's init_parse_vault
143
+ * (generate.c L595): name/type/rating/rows/columns/min-depth/max-depth/flags/D.
144
+ * The C parser's error paths (PARSE_ERROR_VAULT_TOO_BIG against
145
+ * room_builders[i].max_height/max_width, PARSE_ERROR_NO_ROOM_FOUND,
146
+ * PARSE_ERROR_VAULT_DESC_WRONG_LENGTH) are validation of the raw text file and
147
+ * live in the content-pack build, not here. `maxDepth` is z_info->max_depth
148
+ * (constants world:max-depth): a vault max-depth of 0 means "no maximum", so it
149
+ * defaults to maxDepth exactly like parse_vault_max_depth (generate.c L562).
150
+ * Without this, randomVault's `maxLev >= depth` filter hides every 0-max vault
151
+ * (128 of 161) from the dungeon.
152
+ */
153
+ export function loadVaults(records: VaultRecordJson[], maxDepth: number): Vault[] {
154
+ return [...records].reverse().map((r) => ({
155
+ name: r.name,
156
+ typ: r.type,
157
+ rat: r.rating,
158
+ hgt: r.rows,
159
+ wid: r.columns,
160
+ minLev: r["min-depth"] ?? 0,
161
+ maxLev: r["max-depth"] ? r["max-depth"] : maxDepth,
162
+ rows: [...r.D],
163
+ fewEntrances: hasFewEntrances(r.flags),
164
+ }));
165
+ }
166
+
167
+ /** The template/vault data a room registry closes over. */
168
+ export interface RoomData {
169
+ templates: RoomTemplate[];
170
+ vaults: Vault[];
171
+ }
172
+
173
+ /** random_room_template: reservoir pick of a template of a type and rating. */
174
+ function randomRoomTemplate(
175
+ g: Gen,
176
+ templates: RoomTemplate[],
177
+ typ: number,
178
+ rating: number,
179
+ ): RoomTemplate | null {
180
+ let r: RoomTemplate | null = null;
181
+ let n = 1;
182
+ for (const t of templates) {
183
+ if (t.typ === typ && t.rat === rating) {
184
+ if (g.rng.oneIn(n)) r = t;
185
+ n++;
186
+ }
187
+ }
188
+ return r;
189
+ }
190
+
191
+ /** random_vault: reservoir pick of an in-depth vault of a given type. */
192
+ function randomVault(rng: Rng, vaults: Vault[], depth: number, typ: string): Vault | null {
193
+ let r: Vault | null = null;
194
+ let n = 1;
195
+ for (const v of vaults) {
196
+ if (v.typ === typ && v.minLev <= depth && v.maxLev >= depth) {
197
+ if (rng.oneIn(n)) r = v;
198
+ n++;
199
+ }
200
+ }
201
+ return r;
202
+ }
203
+
204
+ function glyphAt(rows: string[], y: number, x: number): string {
205
+ const row = rows[y];
206
+ if (row === undefined) return " ";
207
+ return x < row.length ? (row[x] as string) : " ";
208
+ }
209
+
210
+ /* ------------------------------------------------------------------ *
211
+ * Symmetry transforms (gen-chunk.c).
212
+ * ------------------------------------------------------------------ */
213
+
214
+ const SYMTR_FLAG_NONE = 0;
215
+ const SYMTR_FLAG_NO_ROT = 1;
216
+ const SYMTR_FLAG_NO_REF = 2;
217
+ const SYMTR_FLAG_FORCE_REF = 4;
218
+ const SYMTR_MAX_WEIGHT = 32768;
219
+
220
+ /** symmetry_transform: rotate (clockwise), reflect, then translate. */
221
+ export function symmetryTransform(
222
+ grid: Loc,
223
+ y0: number,
224
+ x0: number,
225
+ height: number,
226
+ width: number,
227
+ rotate: number,
228
+ reflect: boolean,
229
+ ): Loc {
230
+ let x = grid.x;
231
+ let y = grid.y;
232
+ let rheight = height;
233
+ let rwidth = width;
234
+ for (let i = 0; i < rotate % 4; i++) {
235
+ const temp = x;
236
+ x = rheight - 1 - y;
237
+ y = temp;
238
+ const t2 = rwidth;
239
+ rwidth = rheight;
240
+ rheight = t2;
241
+ }
242
+ if (reflect) x = rwidth - 1 - x;
243
+ return loc(x + x0, y + y0);
244
+ }
245
+
246
+ export interface SymmetryResult {
247
+ rotate: number;
248
+ reflect: boolean;
249
+ theight: number;
250
+ twidth: number;
251
+ }
252
+
253
+ /** get_random_symmetry_transform. */
254
+ export function getRandomSymmetryTransform(
255
+ g: Gen,
256
+ height: number,
257
+ width: number,
258
+ flags: number,
259
+ transposeWeightIn: number,
260
+ ): SymmetryResult {
261
+ const w = new Array<number>(9).fill(0);
262
+ const transposeWeight = Math.min(SYMTR_MAX_WEIGHT, Math.max(0, transposeWeightIn));
263
+ w[0] = 0;
264
+ if (flags & SYMTR_FLAG_NO_REF || !(flags & SYMTR_FLAG_FORCE_REF)) {
265
+ w[1] = w[0] + SYMTR_MAX_WEIGHT;
266
+ } else {
267
+ w[1] = w[0];
268
+ }
269
+ if (flags & SYMTR_FLAG_NO_ROT) {
270
+ w[2] = w[1];
271
+ w[3] = w[2];
272
+ w[4] = w[3];
273
+ } else if (flags & SYMTR_FLAG_NO_REF || !(flags & SYMTR_FLAG_FORCE_REF)) {
274
+ w[2] = w[1] + transposeWeight;
275
+ w[3] = w[2] + SYMTR_MAX_WEIGHT;
276
+ w[4] = w[3] + transposeWeight;
277
+ } else {
278
+ w[2] = w[1];
279
+ w[3] = w[2];
280
+ w[4] = w[3];
281
+ }
282
+ if (flags & SYMTR_FLAG_NO_REF) {
283
+ w[5] = w[4];
284
+ w[6] = w[5];
285
+ w[7] = w[6];
286
+ w[8] = w[7];
287
+ } else {
288
+ w[5] = w[4] + SYMTR_MAX_WEIGHT;
289
+ if (flags & SYMTR_FLAG_NO_ROT) {
290
+ w[6] = w[5];
291
+ w[7] = w[6] + SYMTR_MAX_WEIGHT;
292
+ w[8] = w[7];
293
+ } else {
294
+ w[6] = w[5] + transposeWeight;
295
+ w[7] = w[6] + SYMTR_MAX_WEIGHT;
296
+ w[8] = w[7] + transposeWeight;
297
+ }
298
+ }
299
+
300
+ const draw = g.rng.randint0(w[8] as number);
301
+ let ilow = 0;
302
+ let ihigh = 8;
303
+ for (;;) {
304
+ if (ilow === ihigh - 1) break;
305
+ const imid = Math.trunc((ilow + ihigh) / 2);
306
+ if ((w[imid] as number) <= draw) ilow = imid;
307
+ else ihigh = imid;
308
+ }
309
+ const rotate = ilow % 4;
310
+ const reflect = ilow >= 4;
311
+ const theight = rotate === 0 || rotate === 2 ? height : width;
312
+ const twidth = rotate === 0 || rotate === 2 ? width : height;
313
+ return { rotate, reflect, theight, twidth };
314
+ }
315
+
316
+ /** calc_default_transpose_weight. */
317
+ export function calcDefaultTransposeWeight(height: number, width: number): number {
318
+ return (
319
+ Math.trunc(SYMTR_MAX_WEIGHT / 64) *
320
+ Math.max(0, Math.min(64, Math.trunc((128 * height) / width) - 64))
321
+ );
322
+ }
323
+
324
+ /* ------------------------------------------------------------------ *
325
+ * Block reservation and space finding (gen-room.c).
326
+ * ------------------------------------------------------------------ */
327
+
328
+ function checkForUnreservedBlocks(
329
+ g: Gen,
330
+ by1: number,
331
+ bx1: number,
332
+ by2: number,
333
+ bx2: number,
334
+ ): boolean {
335
+ const dun = g.dun;
336
+ if (by1 < 0 || by2 >= dun.rowBlocks) return false;
337
+ if (bx1 < 0 || bx2 >= dun.colBlocks) return false;
338
+ for (let by = by1; by <= by2; by++) {
339
+ const row = dun.roomMap[by];
340
+ if (!row) return false;
341
+ for (let bx = bx1; bx <= bx2; bx++) {
342
+ if (row[bx]) return false;
343
+ }
344
+ }
345
+ return true;
346
+ }
347
+
348
+ function reserveBlocks(g: Gen, by1: number, bx1: number, by2: number, bx2: number): void {
349
+ const dun = g.dun;
350
+ for (let by = by1; by <= by2; by++) {
351
+ const row = dun.roomMap[by] as boolean[];
352
+ for (let bx = bx1; bx <= bx2; bx++) row[bx] = true;
353
+ }
354
+ }
355
+
356
+ /** find_space: reserve blocks for a room and return its centre, or null. */
357
+ function findSpace(g: Gen, height: number, width: number): Loc | null {
358
+ const dun = g.dun;
359
+ const blocksHigh = 1 + Math.trunc((height - 1) / dun.blockHgt);
360
+ const blocksWide = 1 + Math.trunc((width - 1) / dun.blockWid);
361
+ for (let i = 0; i < 25; i++) {
362
+ const by1 = g.rng.randint0(dun.rowBlocks);
363
+ const bx1 = g.rng.randint0(dun.colBlocks);
364
+ const by2 = by1 + blocksHigh - 1;
365
+ const bx2 = bx1 + blocksWide - 1;
366
+ if (!checkForUnreservedBlocks(g, by1, bx1, by2, bx2)) continue;
367
+ const centre = loc(
368
+ Math.trunc(((bx1 + bx2 + 1) * dun.blockWid) / 2),
369
+ Math.trunc(((by1 + by2 + 1) * dun.blockHgt) / 2),
370
+ );
371
+ if (dun.centN < dun.levelRoomMax) {
372
+ dun.cent[dun.centN] = centre;
373
+ dun.centN++;
374
+ }
375
+ reserveBlocks(g, by1, bx1, by2, bx2);
376
+ return centre;
377
+ }
378
+ return null;
379
+ }
380
+
381
+ /** append_entrance: record a marked entrance for the most recent room. */
382
+ function appendEntrance(g: Gen, grid: Loc): void {
383
+ const dun = g.dun;
384
+ if (dun.centN <= 0 || dun.centN > dun.levelRoomMax) return;
385
+ const ridx = dun.centN - 1;
386
+ const list = dun.ent[ridx] ?? (dun.ent[ridx] = []);
387
+ list.push(grid);
388
+ dun.entN[ridx] = list.length;
389
+ dun.ent2room[grid.y * g.c.width + grid.x] = ridx;
390
+ }
391
+
392
+ /* ------------------------------------------------------------------ *
393
+ * build_room_template / build_vault.
394
+ * ------------------------------------------------------------------ */
395
+
396
+ export function buildRoomTemplate(
397
+ g: Gen,
398
+ centreIn: Loc,
399
+ ymax: number,
400
+ xmax: number,
401
+ doors: number,
402
+ rows: string[],
403
+ tval: number,
404
+ fewEntrances: boolean,
405
+ ): boolean {
406
+ const c = g.c;
407
+ const light = c.depth <= g.rng.randint1(25);
408
+ const rnddoors = g.rng.randint1(doors);
409
+ const rndwalls = g.rng.oneIn(2);
410
+
411
+ let rotate: number;
412
+ let reflect: boolean;
413
+ let tymax: number;
414
+ let txmax: number;
415
+ let centre = centreIn;
416
+ if (centre.y >= c.height || centre.x >= c.width) {
417
+ const s = getRandomSymmetryTransform(
418
+ g,
419
+ ymax,
420
+ xmax,
421
+ SYMTR_FLAG_NONE,
422
+ calcDefaultTransposeWeight(ymax, xmax),
423
+ );
424
+ rotate = s.rotate;
425
+ reflect = s.reflect;
426
+ tymax = s.theight;
427
+ txmax = s.twidth;
428
+ const found = findSpace(g, tymax + 2, txmax + 2);
429
+ if (!found) return false;
430
+ centre = found;
431
+ } else {
432
+ const s = getRandomSymmetryTransform(g, ymax, xmax, SYMTR_FLAG_NONE, 0);
433
+ rotate = s.rotate;
434
+ reflect = s.reflect;
435
+ tymax = s.theight;
436
+ txmax = s.twidth;
437
+ }
438
+
439
+ centre = loc(centre.x - Math.trunc(txmax / 2), centre.y - Math.trunc(tymax / 2));
440
+
441
+ /* First pass: features. */
442
+ for (let dy = 0; dy < ymax; dy++) {
443
+ for (let dx = 0; dx < xmax; dx++) {
444
+ const t = glyphAt(rows, dy, dx);
445
+ const grid = symmetryTransform(loc(dx, dy), centre.y, centre.x, ymax, xmax, rotate, reflect);
446
+ if (t === " ") continue;
447
+ c.setFeat(grid, FEAT.FLOOR);
448
+ switch (t) {
449
+ case "%":
450
+ setMarkedGranite(c, grid, SQUARE.WALL_OUTER);
451
+ if (fewEntrances) appendEntrance(g, grid);
452
+ break;
453
+ case "#":
454
+ setMarkedGranite(c, grid, SQUARE.WALL_SOLID);
455
+ break;
456
+ case "+":
457
+ placeClosedDoor(g, grid);
458
+ break;
459
+ case "^":
460
+ if (g.rng.oneIn(4)) placeTrap(g, grid);
461
+ break;
462
+ case "x":
463
+ if (rndwalls) setMarkedGranite(c, grid, SQUARE.WALL_SOLID);
464
+ break;
465
+ case "(":
466
+ if (rndwalls) placeSecretDoor(c, grid);
467
+ break;
468
+ case ")":
469
+ if (!rndwalls) placeSecretDoor(c, grid);
470
+ else setMarkedGranite(c, grid, SQUARE.WALL_SOLID);
471
+ break;
472
+ case "8":
473
+ if (g.rng.randint0(100) < 80 || g.dun.persist) {
474
+ /* build_room_template '8' (gen-room.c L1211): ORIGIN_SPECIAL. */
475
+ placeObject(g, grid, c.depth, false, false, 0, ORIGIN.SPECIAL);
476
+ } else {
477
+ placeRandomStairs(g, grid, g.dun.quest);
478
+ }
479
+ break;
480
+ case "9":
481
+ break;
482
+ case "[":
483
+ /* build_room_template '[' (gen-room.c L1226): ORIGIN_SPECIAL. */
484
+ placeObject(g, grid, c.depth, false, false, tval, ORIGIN.SPECIAL);
485
+ break;
486
+ case "1":
487
+ case "2":
488
+ case "3":
489
+ case "4":
490
+ case "5":
491
+ case "6": {
492
+ const doorpos = t.charCodeAt(0) - "0".charCodeAt(0);
493
+ if (doorpos === rnddoors) placeSecretDoor(c, grid);
494
+ else setMarkedGranite(c, grid, SQUARE.WALL_SOLID);
495
+ break;
496
+ }
497
+ }
498
+ c.sqinfoOn(grid, SQUARE.ROOM);
499
+ if (light) c.sqinfoOn(grid, SQUARE.GLOW);
500
+ }
501
+ }
502
+
503
+ /* Second pass: inner-wall conversion, monsters/objects at 8 and 9. */
504
+ for (let dy = 0; dy < ymax; dy++) {
505
+ for (let dx = 0; dx < xmax; dx++) {
506
+ const t = glyphAt(rows, dy, dx);
507
+ const grid = symmetryTransform(loc(dx, dy), centre.y, centre.x, ymax, xmax, rotate, reflect);
508
+ switch (t) {
509
+ case "#":
510
+ if (countNeighbors(c, grid, squareIsRoom, false) === 8) {
511
+ c.sqinfoOff(grid, SQUARE.WALL_SOLID);
512
+ c.sqinfoOn(grid, SQUARE.WALL_INNER);
513
+ }
514
+ break;
515
+ case "8":
516
+ vaultMonsters(g, grid, c.depth + 2, g.rng.randint0(2) + 3);
517
+ break;
518
+ case "9": {
519
+ const off2 = loc(2, -2);
520
+ const off3 = loc(3, 3);
521
+ vaultMonsters(g, locDiff(grid, off3), c.depth + g.rng.randint0(2), g.rng.randint1(2));
522
+ vaultMonsters(g, locSum(grid, off3), c.depth + g.rng.randint0(2), g.rng.randint1(2));
523
+ if (g.rng.oneIn(2)) vaultObjects(g, locSum(grid, off2), c.depth, 1 + g.rng.randint0(2));
524
+ if (g.rng.oneIn(2)) vaultObjects(g, locDiff(grid, off2), c.depth, 1 + g.rng.randint0(2));
525
+ break;
526
+ }
527
+ default:
528
+ break;
529
+ }
530
+ }
531
+ }
532
+ return true;
533
+ }
534
+
535
+ function buildRoomTemplateType(
536
+ g: Gen,
537
+ centre: Loc,
538
+ typ: number,
539
+ rating: number,
540
+ templates: RoomTemplate[],
541
+ ): boolean {
542
+ const room = randomRoomTemplate(g, templates, typ, rating);
543
+ if (!room) return false;
544
+ return buildRoomTemplate(
545
+ g,
546
+ centre,
547
+ room.hgt,
548
+ room.wid,
549
+ room.dor,
550
+ room.rows,
551
+ room.tval,
552
+ room.fewEntrances,
553
+ );
554
+ }
555
+
556
+ const TV_CHEST = tvalFindIdx("chest");
557
+ const TV_RING = tvalFindIdx("ring");
558
+ const TV_AMULET = tvalFindIdx("amulet");
559
+ const TV_POTION = tvalFindIdx("potion");
560
+ const TV_SCROLL = tvalFindIdx("scroll");
561
+ const TV_STAFF = tvalFindIdx("staff");
562
+ const TV_WAND = tvalFindIdx("wand");
563
+ const TV_ROD = tvalFindIdx("rod");
564
+ const TV_FOOD = tvalFindIdx("food");
565
+ const TV_BOOTS = tvalFindIdx("boots");
566
+ const TV_GLOVES = tvalFindIdx("gloves");
567
+ const TV_HELM = tvalFindIdx("helm");
568
+ const TV_CROWN = tvalFindIdx("crown");
569
+ const TV_SHIELD = tvalFindIdx("shield");
570
+ const TV_CLOAK = tvalFindIdx("cloak");
571
+ const TV_SOFT_ARMOR = tvalFindIdx("soft armour");
572
+ const TV_HARD_ARMOR = tvalFindIdx("hard armour");
573
+ const TV_DRAG_ARMOR = tvalFindIdx("dragon armour");
574
+ const TV_SWORD = tvalFindIdx("sword");
575
+ const TV_POLEARM = tvalFindIdx("polearm");
576
+ const TV_HAFTED = tvalFindIdx("hafted");
577
+ const TV_BOW = tvalFindIdx("bow");
578
+
579
+ function isAlpha(ch: string): boolean {
580
+ return /^[A-Za-z]$/.test(ch);
581
+ }
582
+
583
+ /** build_vault: draw a vault from its grid text. */
584
+ export function buildVault(g: Gen, centreIn: Loc, v: Vault): boolean {
585
+ const c = g.c;
586
+ let rotate: number;
587
+ let reflect: boolean;
588
+ let thgt: number;
589
+ let twid: number;
590
+ let centre = centreIn;
591
+ if (centre.y >= c.height || centre.x >= c.width) {
592
+ const s = getRandomSymmetryTransform(
593
+ g,
594
+ v.hgt,
595
+ v.wid,
596
+ SYMTR_FLAG_NONE,
597
+ calcDefaultTransposeWeight(v.hgt, v.wid),
598
+ );
599
+ rotate = s.rotate;
600
+ reflect = s.reflect;
601
+ thgt = s.theight;
602
+ twid = s.twidth;
603
+ const found = findSpace(g, thgt + 2, twid + 2);
604
+ if (!found) return false;
605
+ centre = found;
606
+ } else {
607
+ const s = getRandomSymmetryTransform(g, v.hgt, v.wid, SYMTR_FLAG_NONE, 0);
608
+ rotate = s.rotate;
609
+ reflect = s.reflect;
610
+ thgt = s.theight;
611
+ twid = s.twidth;
612
+ }
613
+
614
+ centre = loc(centre.x - Math.trunc(twid / 2), centre.y - Math.trunc(thgt / 2));
615
+
616
+ const y1 = centre.y;
617
+ const x1 = centre.x;
618
+ const y2 = y1 + thgt - 1;
619
+ const x2 = x1 + twid - 1;
620
+
621
+ /* No random monsters in vaults. */
622
+ generateMark(c, y1, x1, y2, x2, SQUARE.MON_RESTRICT);
623
+
624
+ /* Racial monster symbols, collected in first-appearance order (max 30). */
625
+ const racialSymbol: string[] = [];
626
+
627
+ /* First pass: features. */
628
+ for (let y = 0; y < v.hgt; y++) {
629
+ for (let x = 0; x < v.wid; x++) {
630
+ const t = glyphAt(v.rows, y, x);
631
+ const grid = symmetryTransform(loc(x, y), centre.y, centre.x, v.hgt, v.wid, rotate, reflect);
632
+ if (t === " ") continue;
633
+ c.setFeat(grid, FEAT.FLOOR);
634
+ let icky = true;
635
+ switch (t) {
636
+ case "%":
637
+ setMarkedGranite(c, grid, SQUARE.WALL_OUTER);
638
+ if (v.fewEntrances) appendEntrance(g, grid);
639
+ icky = false;
640
+ break;
641
+ case "#":
642
+ setMarkedGranite(c, grid, SQUARE.WALL_SOLID);
643
+ break;
644
+ case "@":
645
+ c.setFeat(grid, FEAT.PERM);
646
+ break;
647
+ case "*":
648
+ c.setFeat(grid, g.rng.oneIn(2) ? FEAT.MAGMA_K : FEAT.QUARTZ_K);
649
+ break;
650
+ case ":":
651
+ c.setFeat(grid, g.rng.oneIn(2) ? FEAT.PASS_RUBBLE : FEAT.RUBBLE);
652
+ break;
653
+ case "+":
654
+ placeSecretDoor(c, grid);
655
+ break;
656
+ case "^":
657
+ if (g.rng.oneIn(4)) placeTrap(g, grid);
658
+ break;
659
+ case "&":
660
+ /* build_vault '&' (gen-room.c L1474): ORIGIN_VAULT. */
661
+ if (g.rng.randint0(100) < 75) placeObject(g, grid, c.depth, false, false, 0, ORIGIN.VAULT);
662
+ else if (g.rng.oneIn(4)) placeTrap(g, grid);
663
+ break;
664
+ case "<":
665
+ if (!g.dun.persist) c.setFeat(grid, FEAT.LESS);
666
+ break;
667
+ case ">":
668
+ if (!g.dun.persist) {
669
+ if (g.dun.quest || c.depth >= g.constants.maxDepth - 1) c.setFeat(grid, FEAT.LESS);
670
+ else c.setFeat(grid, FEAT.MORE);
671
+ }
672
+ break;
673
+ case "`":
674
+ c.setFeat(grid, FEAT.LAVA);
675
+ break;
676
+ case "/":
677
+ case ";":
678
+ break;
679
+ }
680
+ c.sqinfoOn(grid, SQUARE.ROOM);
681
+ if (icky) c.sqinfoOn(grid, SQUARE.VAULT);
682
+ }
683
+ }
684
+
685
+ /* Second pass: monsters, objects, inner-wall conversion. */
686
+ for (let y = 0; y < v.hgt; y++) {
687
+ for (let x = 0; x < v.wid; x++) {
688
+ const t = glyphAt(v.rows, y, x);
689
+ const grid = symmetryTransform(loc(x, y), centre.y, centre.x, v.hgt, v.wid, rotate, reflect);
690
+ if (t === " ") continue;
691
+ if (isAlpha(t) && t !== "x" && t !== "X") {
692
+ /* Racial monster glyph: store the symbol, place later via
693
+ * get_vault_monsters (mon_select restriction, item #75). */
694
+ if (!racialSymbol.includes(t) && racialSymbol.length < 30) {
695
+ racialSymbol.push(t);
696
+ }
697
+ continue;
698
+ }
699
+ switch (t) {
700
+ case "1":
701
+ if (g.rng.oneIn(2)) {
702
+ /* build_vault '1' (gen-room.c L1540-1541): ORIGIN_DROP_VAULT. */
703
+ pickAndPlaceMonster(g, grid, c.depth, true, true, ORIGIN.DROP_VAULT);
704
+ } else if (g.rng.oneIn(2)) {
705
+ /* build_vault '1' (gen-room.c L1543): ORIGIN_VAULT. */
706
+ placeObject(g, grid, c.depth, g.rng.oneIn(8), false, 0, ORIGIN.VAULT);
707
+ } else if (g.rng.oneIn(4)) {
708
+ placeTrap(g, grid);
709
+ }
710
+ break;
711
+ case "2":
712
+ pickAndPlaceMonster(g, grid, c.depth + 5, true, true, ORIGIN.DROP_VAULT);
713
+ break;
714
+ case "3":
715
+ /* build_vault '3' (gen-room.c L1556): ORIGIN_VAULT. */
716
+ placeObject(g, grid, c.depth + 3, false, false, 0, ORIGIN.VAULT);
717
+ break;
718
+ case "4":
719
+ if (g.rng.oneIn(2)) {
720
+ pickAndPlaceMonster(g, grid, c.depth + 3, true, true, ORIGIN.DROP_VAULT);
721
+ }
722
+ /* build_vault '4' (gen-room.c L1564): ORIGIN_VAULT. */
723
+ if (g.rng.oneIn(2)) placeObject(g, grid, c.depth + 7, false, false, 0, ORIGIN.VAULT);
724
+ break;
725
+ case "5":
726
+ /* build_vault '5' (gen-room.c L1569): ORIGIN_VAULT. */
727
+ placeObject(g, grid, c.depth + 7, false, false, 0, ORIGIN.VAULT);
728
+ break;
729
+ case "6":
730
+ pickAndPlaceMonster(g, grid, c.depth + 11, true, true, ORIGIN.DROP_VAULT);
731
+ break;
732
+ case "7":
733
+ /* build_vault '7' (gen-room.c L1576): ORIGIN_VAULT. */
734
+ placeObject(g, grid, c.depth + 15, false, false, 0, ORIGIN.VAULT);
735
+ break;
736
+ case "0":
737
+ pickAndPlaceMonster(g, grid, c.depth + 20, true, true, ORIGIN.DROP_VAULT);
738
+ break;
739
+ case "9":
740
+ pickAndPlaceMonster(g, grid, c.depth + 9, true, true, ORIGIN.DROP_VAULT);
741
+ /* build_vault '9' (gen-room.c L1586): ORIGIN_VAULT. */
742
+ placeObject(g, grid, c.depth + 7, true, false, 0, ORIGIN.VAULT);
743
+ break;
744
+ case "8":
745
+ pickAndPlaceMonster(g, grid, c.depth + 40, true, true, ORIGIN.DROP_VAULT);
746
+ /* build_vault '8' (gen-room.c L1594): ORIGIN_VAULT. */
747
+ placeObject(g, grid, c.depth + 20, true, true, 0, ORIGIN.VAULT);
748
+ break;
749
+ case "~":
750
+ /* build_vault '~' (gen-room.c L1599): ORIGIN_VAULT. */
751
+ placeObject(g, grid, c.depth + 5, false, false, TV_CHEST, ORIGIN.VAULT);
752
+ break;
753
+ case "$":
754
+ /* build_vault '$' (gen-room.c L1602): ORIGIN_VAULT. */
755
+ placeGold(g, grid, c.depth, ORIGIN.VAULT);
756
+ break;
757
+ case "]": {
758
+ const temp = g.rng.oneIn(3) ? g.rng.randint1(9) : g.rng.randint1(8);
759
+ const tval = [
760
+ 0,
761
+ TV_BOOTS,
762
+ TV_GLOVES,
763
+ TV_HELM,
764
+ TV_CROWN,
765
+ TV_SHIELD,
766
+ TV_CLOAK,
767
+ TV_SOFT_ARMOR,
768
+ TV_HARD_ARMOR,
769
+ TV_DRAG_ARMOR,
770
+ ][temp] as number;
771
+ /* build_vault ']' (gen-room.c L1617): ORIGIN_VAULT. */
772
+ placeObject(g, grid, c.depth + 3, true, false, tval, ORIGIN.VAULT);
773
+ break;
774
+ }
775
+ case "|": {
776
+ const temp = g.rng.randint1(4);
777
+ const tval = [0, TV_SWORD, TV_POLEARM, TV_HAFTED, TV_BOW][temp] as number;
778
+ /* build_vault '|' (gen-room.c L1630): ORIGIN_VAULT. */
779
+ placeObject(g, grid, c.depth + 3, true, false, tval, ORIGIN.VAULT);
780
+ break;
781
+ }
782
+ case "=":
783
+ /* build_vault '=' (gen-room.c L1635): ORIGIN_VAULT. */
784
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, TV_RING, ORIGIN.VAULT);
785
+ break;
786
+ case '"':
787
+ /* build_vault '"' (gen-room.c L1638): ORIGIN_VAULT. */
788
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, TV_AMULET, ORIGIN.VAULT);
789
+ break;
790
+ case "!":
791
+ /* build_vault '!' (gen-room.c L1641): ORIGIN_VAULT. */
792
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, TV_POTION, ORIGIN.VAULT);
793
+ break;
794
+ case "?":
795
+ /* build_vault '?' (gen-room.c L1644): ORIGIN_VAULT. */
796
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, TV_SCROLL, ORIGIN.VAULT);
797
+ break;
798
+ case "_":
799
+ /* build_vault '_' (gen-room.c L1647): ORIGIN_VAULT. */
800
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, TV_STAFF, ORIGIN.VAULT);
801
+ break;
802
+ case "-":
803
+ /* build_vault '-' (gen-room.c L1650): ORIGIN_VAULT. */
804
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, g.rng.oneIn(2) ? TV_WAND : TV_ROD, ORIGIN.VAULT);
805
+ break;
806
+ case ",":
807
+ /* build_vault ',' (gen-room.c L1655): ORIGIN_VAULT. */
808
+ placeObject(g, grid, c.depth + 3, g.rng.oneIn(4), false, TV_FOOD, ORIGIN.VAULT);
809
+ break;
810
+ case "#":
811
+ if (countNeighbors(c, grid, squareIsRoom, false) === 8) {
812
+ c.sqinfoOff(grid, SQUARE.WALL_SOLID);
813
+ c.sqinfoOn(grid, SQUARE.WALL_INNER);
814
+ }
815
+ break;
816
+ case "@":
817
+ if (countNeighbors(c, grid, squareIsRoom, false) === 8) {
818
+ c.sqinfoOn(grid, SQUARE.WALL_INNER);
819
+ }
820
+ break;
821
+ }
822
+ }
823
+ }
824
+
825
+ /* Place specified monsters (get_vault_monsters). The upstream loop reads
826
+ * the raw vault text linearly across the rectangle, so map the linear
827
+ * index back to the vault's original width. */
828
+ getVaultMonsters(
829
+ g,
830
+ racialSymbol,
831
+ v.typ,
832
+ (i) => glyphAt(v.rows, Math.trunc(i / v.wid), i % v.wid),
833
+ y1,
834
+ y2,
835
+ x1,
836
+ x2,
837
+ );
838
+
839
+ return true;
840
+ }
841
+
842
+ /**
843
+ * build_vault_type (gen-room.c L1712): the shared body behind build_interesting
844
+ * (L2988), build_lesser_vault (L3001), build_lesser_new_vault (L3014),
845
+ * build_medium_vault (L3027) and build_medium_new_vault (L3040). Those five
846
+ * upstream builders differ ONLY in the vault type string they pass; they add no
847
+ * rating or flag adjustments of their own. The two greater-vault builders
848
+ * (L3112, L3125) are NOT plain wrappers - they go through help_greater_vault.
849
+ */
850
+ function buildVaultType(g: Gen, centre: Loc, typ: string, vaults: Vault[]): boolean {
851
+ const v = randomVault(g.rng, vaults, g.c.depth, typ);
852
+ if (!v) return false;
853
+ if (!buildVault(g, centre, v)) return false;
854
+ /* Boost the rating (gen-room.c L1728). */
855
+ g.c.addToMonsterRating(v.rat);
856
+ return true;
857
+ }
858
+
859
+ /**
860
+ * help_greater_vault (gen-room.c L3075): the gate that build_greater_vault
861
+ * (L3112) and build_greater_new_vault (L3125) share, and the ONLY difference
862
+ * between them and the plain build_vault_type wrappers above.
863
+ *
864
+ * dungeon_profile.txt deliberately gives greater vaults an artificially high
865
+ * allocation cutoff (100 in "classic", 50/100 in the newer profiles) because
866
+ * this helper cancels nearly every attempt. Skipping it makes a greater vault
867
+ * the first room of essentially every level at depth 35+.
868
+ *
869
+ * Three guarantees, in upstream order (only the second and third draw RNG):
870
+ * 1. L3086-3087: only as the FIRST non-staircase room. When the caller supplies
871
+ * a real centre, room_build has already incremented cent_n, so the cap is 1;
872
+ * when the builder finds its own space it is 0.
873
+ * 2. L3089-3096: a depth ladder - 1/3 at depth 90+, 2/9 at 80-89, 4/27 at
874
+ * 70-79 ... 512/59049 at depth 0. One randint0(denominator) draw.
875
+ * 3. L3098-3099: profiles other than "classic" reject a further 2/3, so the
876
+ * newer profiles (which list two greater-vault entries) end up with roughly
877
+ * the classic frequency.
878
+ */
879
+ function helpGreaterVault(g: Gen, centre: Loc, name: string, vaults: Vault[]): boolean {
880
+ const c = g.c;
881
+ const dun = g.dun;
882
+ let numerator = 1;
883
+ let denominator = 3;
884
+
885
+ const findingSpace = centre.y >= c.height || centre.x >= c.width;
886
+ if (dun.centN - dun.nstairRoom > (findingSpace ? 0 : 1)) return false;
887
+
888
+ /* Level 90+ has a 1/3 chance, level 80-89 has 2/9, ... */
889
+ for (let i = 90; i > c.depth; i -= 10) {
890
+ numerator *= 2;
891
+ denominator *= 3;
892
+ }
893
+
894
+ /* Attempt to pass the depth check and build a GV. */
895
+ if (g.rng.randint0(denominator) >= numerator) return false;
896
+
897
+ /* Non-classic profiles need to adjust the probability. */
898
+ if (dun.profileName !== "classic" && !g.rng.oneIn(3)) return false;
899
+
900
+ return buildVaultType(g, centre, name, vaults);
901
+ }
902
+
903
+ /**
904
+ * vault_chunk (gen-cave.c L3212): build a fresh chunk that consists only of a
905
+ * greater vault, filled around with granite. Picks a greater-vault type at the
906
+ * given depth (one_in_(2) chooses the "(new)" variant), sizes a sub-chunk to
907
+ * the vault, and builds the vault into it via build_vault. NEW exported helper.
908
+ *
909
+ * `makeSubGen(height, width, depth)` mints a Gen bound to a fresh sub-chunk of
910
+ * that size (supplied by the caller so Gen/Chunk construction stays in cave.ts
911
+ * and there is no circular import). The vault's name/type draws happen on the
912
+ * shared `rng` before the sub-chunk exists, so RNG order is preserved.
913
+ *
914
+ * Returns the built sub-chunk's Gen, or null on failure (no greater vault at
915
+ * depth, or build_vault failed). Faithful to the C control flow (return failure
916
+ * on either path); the C-side uncreate_artifacts/cave_free cleanup is not
917
+ * needed because the caller simply discards this sub-chunk on failure.
918
+ */
919
+ export function vaultChunk(
920
+ rng: Rng,
921
+ vaults: Vault[],
922
+ depth: number,
923
+ makeSubGen: (height: number, width: number, depth: number) => Gen,
924
+ ): Gen | null {
925
+ const vname = rng.oneIn(2) ? "Greater vault (new)" : "Greater vault";
926
+ const v = randomVault(rng, vaults, depth, vname);
927
+ if (!v) return null;
928
+
929
+ const g = makeSubGen(v.hgt, v.wid, depth);
930
+ const c = g.c;
931
+
932
+ /* Fill with granite; the vault will override for the grids it sets. */
933
+ fillRectangle(c, 0, 0, v.hgt - 1, v.wid - 1, FEAT.GRANITE, SQUARE.NONE);
934
+
935
+ /* Build the vault in it. */
936
+ g.dun.centN = 0;
937
+ g.dun.resetEntranceData(c);
938
+ const built = buildVault(g, loc(Math.trunc(v.wid / 2), Math.trunc(v.hgt / 2)), v);
939
+ if (!built) return null;
940
+
941
+ return g;
942
+ }
943
+
944
+ /* ------------------------------------------------------------------ *
945
+ * Geometric builders.
946
+ * ------------------------------------------------------------------ */
947
+
948
+ /** build_staircase: a 1x1 staircase room for persistent levels. */
949
+ function buildStaircase(g: Gen, _centre: Loc, _rating: number): boolean {
950
+ const c = g.c;
951
+ const join = g.dun.currJoin;
952
+ if (!join) return false;
953
+ const centre = join.grid;
954
+ if (centre.y < 1 || centre.y > c.height - 2 || centre.x < 1 || centre.x > c.width - 2) {
955
+ return false;
956
+ }
957
+ const tl = loc(centre.x - (centre.x > 1 ? 2 : 1), centre.y - (centre.y > 1 ? 2 : 1));
958
+ const br = loc(
959
+ centre.x + (centre.x < c.width - 2 ? 2 : 1),
960
+ centre.y + (centre.y < c.height - 2 ? 2 : 1),
961
+ );
962
+ const by1 = Math.trunc(tl.y / g.dun.blockHgt);
963
+ const bx1 = Math.trunc(tl.x / g.dun.blockWid);
964
+ const by2 = Math.trunc(br.y / g.dun.blockHgt);
965
+ const bx2 = Math.trunc(br.x / g.dun.blockWid);
966
+ if (g.dun.blockHgt > 1 || g.dun.blockWid > 1) {
967
+ for (let y = tl.y; y <= br.y; y++) {
968
+ for (let x = tl.x; x <= br.x; x++) {
969
+ if (squareIsRoom(c, loc(x, y))) return false;
970
+ }
971
+ }
972
+ } else if (!checkForUnreservedBlocks(g, by1, bx1, by2, bx2)) {
973
+ return false;
974
+ }
975
+ reserveBlocks(g, by1, bx1, by2, bx2);
976
+ if (g.dun.centN < g.dun.levelRoomMax) {
977
+ g.dun.cent[g.dun.centN] = centre;
978
+ g.dun.centN++;
979
+ }
980
+ generateRoom(c, centre.y - 1, centre.x - 1, centre.y + 1, centre.x + 1, false);
981
+ drawRectangle(c, centre.y - 1, centre.x - 1, centre.y + 1, centre.x + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
982
+ c.setFeat(centre, join.feat);
983
+ return true;
984
+ }
985
+
986
+ function buildCircular(g: Gen, centreIn: Loc, _rating: number): boolean {
987
+ const c = g.c;
988
+ const radius = 2 + g.rng.randint1(2) + g.rng.randint1(3);
989
+ const light = c.depth <= g.rng.randint1(25);
990
+ let centre = centreIn;
991
+ if (centre.y >= c.height || centre.x >= c.width) {
992
+ const found = findSpace(g, 2 * radius + 10, 2 * radius + 10);
993
+ if (!found) return false;
994
+ centre = found;
995
+ }
996
+ fillCircle(c, centre.y, centre.x, radius + 1, 0, FEAT.FLOOR, SQUARE.NONE, light);
997
+ setBorderingWalls(c, centre.y - radius - 2, centre.x - radius - 2, centre.y + radius + 2, centre.x + radius + 2);
998
+ if (radius - 4 > 0 && g.rng.randint0(4) < radius - 4) {
999
+ const offset = randDir(g.rng);
1000
+ drawRectangle(c, centre.y - 2, centre.x - 2, centre.y + 2, centre.x + 2, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1001
+ placeClosedDoor(g, loc(centre.x + offset.x * 2, centre.y + offset.y * 2));
1002
+ vaultObjects(g, centre, c.depth, g.rng.randint0(2));
1003
+ vaultMonsters(g, centre, c.depth + 1, g.rng.randint0(3));
1004
+ }
1005
+ return true;
1006
+ }
1007
+
1008
+ function buildSimple(g: Gen, centreIn: Loc, _rating: number): boolean {
1009
+ const c = g.c;
1010
+ const height = 1 + g.rng.randint1(4) + g.rng.randint1(3);
1011
+ const width = 1 + g.rng.randint1(11) + g.rng.randint1(11);
1012
+ let centre = centreIn;
1013
+ if (centre.y >= c.height || centre.x >= c.width) {
1014
+ const found = findSpace(g, height + 2, width + 2);
1015
+ if (!found) return false;
1016
+ centre = found;
1017
+ }
1018
+ const y1 = centre.y - Math.trunc(height / 2);
1019
+ const x1 = centre.x - Math.trunc(width / 2);
1020
+ const y2 = y1 + height - 1;
1021
+ const x2 = x1 + width - 1;
1022
+ const light = c.depth <= g.rng.randint1(25);
1023
+
1024
+ generateRoom(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, light);
1025
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1026
+ fillRectangle(c, y1, x1, y2, x2, FEAT.FLOOR, SQUARE.NONE);
1027
+
1028
+ if (g.rng.oneIn(20)) {
1029
+ const offx = (x2 - x1) % 2 === 0 ? 0 : g.rng.randint0(2);
1030
+ const offy = (y2 - y1) % 2 === 0 ? 0 : g.rng.randint0(2);
1031
+ for (let y = y1 + offy; y <= y2; y += 2) {
1032
+ for (let x = x1 + offx; x <= x2; x += 2) setMarkedGranite(c, loc(x, y), SQUARE.WALL_INNER);
1033
+ }
1034
+ if (!offy) {
1035
+ if (!offx) {
1036
+ c.sqinfoOff(loc(x1 - 1, y1 - 1), SQUARE.ROOM);
1037
+ c.sqinfoOff(loc(x1 - 1, y1 - 1), SQUARE.WALL_OUTER);
1038
+ }
1039
+ if ((x2 - x1 - offx) % 2 === 0) {
1040
+ c.sqinfoOff(loc(x2 + 1, y1 - 1), SQUARE.ROOM);
1041
+ c.sqinfoOff(loc(x2 + 1, y1 - 1), SQUARE.WALL_OUTER);
1042
+ }
1043
+ }
1044
+ if ((y2 - y1 - offy) % 2 === 0) {
1045
+ if (!offx) {
1046
+ c.sqinfoOff(loc(x1 - 1, y2 + 1), SQUARE.ROOM);
1047
+ c.sqinfoOff(loc(x1 - 1, y2 + 1), SQUARE.WALL_OUTER);
1048
+ }
1049
+ if ((x2 - x1 - offx) % 2 === 0) {
1050
+ c.sqinfoOff(loc(x2 + 1, y2 + 1), SQUARE.ROOM);
1051
+ c.sqinfoOff(loc(x2 + 1, y2 + 1), SQUARE.WALL_OUTER);
1052
+ }
1053
+ }
1054
+ } else if (g.rng.oneIn(50)) {
1055
+ const offx = (x2 - x1) % 2 === 0 ? 0 : g.rng.randint0(2);
1056
+ const offy = (y2 - y1) % 2 === 0 ? 0 : g.rng.randint0(2);
1057
+ for (let y = y1 + 2 + offy; y <= y2 - 2; y += 2) {
1058
+ setMarkedGranite(c, loc(x1, y), SQUARE.WALL_INNER);
1059
+ setMarkedGranite(c, loc(x2, y), SQUARE.WALL_INNER);
1060
+ }
1061
+ for (let x = x1 + 2 + offx; x <= x2 - 2; x += 2) {
1062
+ setMarkedGranite(c, loc(x, y1), SQUARE.WALL_INNER);
1063
+ setMarkedGranite(c, loc(x, y2), SQUARE.WALL_INNER);
1064
+ }
1065
+ }
1066
+ return true;
1067
+ }
1068
+
1069
+ function buildOverlap(g: Gen, centreIn: Loc, _rating: number): boolean {
1070
+ const c = g.c;
1071
+ const light = c.depth <= g.rng.randint1(25);
1072
+ let y1a = g.rng.randint1(4);
1073
+ let x1a = g.rng.randint1(11);
1074
+ let y2a = g.rng.randint1(3);
1075
+ let x2a = g.rng.randint1(10);
1076
+ let y1b = g.rng.randint1(3);
1077
+ let x1b = g.rng.randint1(10);
1078
+ let y2b = g.rng.randint1(4);
1079
+ let x2b = g.rng.randint1(11);
1080
+ const height = 2 * Math.max(Math.max(y1a, y2a), Math.max(y1b, y2b)) + 1;
1081
+ const width = 2 * Math.max(Math.max(x1a, x2a), Math.max(x1b, x2b)) + 1;
1082
+
1083
+ let centre = centreIn;
1084
+ if (centre.y >= c.height || centre.x >= c.width) {
1085
+ const found = findSpace(g, height + 2, width + 2);
1086
+ if (!found) return false;
1087
+ centre = found;
1088
+ }
1089
+ y1a = centre.y - y1a;
1090
+ x1a = centre.x - x1a;
1091
+ y2a = centre.y + y2a;
1092
+ x2a = centre.x + x2a;
1093
+ y1b = centre.y - y1b;
1094
+ x1b = centre.x - x1b;
1095
+ y2b = centre.y + y2b;
1096
+ x2b = centre.x + x2b;
1097
+
1098
+ generateRoom(c, y1a - 1, x1a - 1, y2a + 1, x2a + 1, light);
1099
+ generateRoom(c, y1b - 1, x1b - 1, y2b + 1, x2b + 1, light);
1100
+ drawRectangle(c, y1a - 1, x1a - 1, y2a + 1, x2a + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1101
+ drawRectangle(c, y1b - 1, x1b - 1, y2b + 1, x2b + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1102
+ fillRectangle(c, y1a, x1a, y2a, x2a, FEAT.FLOOR, SQUARE.NONE);
1103
+ fillRectangle(c, y1b, x1b, y2b, x2b, FEAT.FLOOR, SQUARE.NONE);
1104
+ return true;
1105
+ }
1106
+
1107
+ function buildCrossed(g: Gen, centreIn: Loc, _rating: number): boolean {
1108
+ const c = g.c;
1109
+ const light = c.depth <= g.rng.randint1(25);
1110
+ const wy = 1;
1111
+ const wx = 1;
1112
+ const dy = g.rng.randRange(3, 4);
1113
+ const dx = g.rng.randRange(3, 11);
1114
+ const height = Math.max(dy + dy + 1, wy + wy + 1);
1115
+ const width = Math.max(wx + wx + 1, dx + dx + 1);
1116
+
1117
+ let centre = centreIn;
1118
+ if (centre.y >= c.height || centre.x >= c.width) {
1119
+ const found = findSpace(g, height + 2, width + 2);
1120
+ if (!found) return false;
1121
+ centre = found;
1122
+ }
1123
+ const y1a = centre.y - dy;
1124
+ const x1a = centre.x - wx;
1125
+ const y2a = centre.y + dy;
1126
+ const x2a = centre.x + wx;
1127
+ const y1b = centre.y - wy;
1128
+ const x1b = centre.x - dx;
1129
+ const y2b = centre.y + wy;
1130
+ const x2b = centre.x + dx;
1131
+
1132
+ generateRoom(c, y1a - 1, x1a - 1, y2a + 1, x2a + 1, light);
1133
+ generateRoom(c, y1b - 1, x1b - 1, y2b + 1, x2b + 1, light);
1134
+ drawRectangle(c, y1a - 1, x1a - 1, y2a + 1, x2a + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1135
+ drawRectangle(c, y1b - 1, x1b - 1, y2b + 1, x2b + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1136
+ fillRectangle(c, y1a, x1a, y2a, x2a, FEAT.FLOOR, SQUARE.NONE);
1137
+ fillRectangle(c, y1b, x1b, y2b, x2b, FEAT.FLOOR, SQUARE.NONE);
1138
+
1139
+ switch (g.rng.randint1(4)) {
1140
+ case 1:
1141
+ break;
1142
+ case 2:
1143
+ fillRectangle(c, y1b, x1a, y2b, x2a, FEAT.GRANITE, SQUARE.WALL_INNER);
1144
+ break;
1145
+ case 3:
1146
+ drawRectangle(c, y1b, x1a, y2b, x2a, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1147
+ generateHole(g.rng, c, y1b, x1a, y2b, x2a, FEAT.SECRET);
1148
+ /* build_crossed case 3 (gen-room.c L2315): ORIGIN_SPECIAL. */
1149
+ placeObject(g, centre, c.depth, false, false, 0, ORIGIN.SPECIAL);
1150
+ vaultMonsters(g, centre, c.depth + 2, g.rng.randint0(2) + 3);
1151
+ vaultTraps(g, centre, 4, 4, g.rng.randint0(3) + 2);
1152
+ break;
1153
+ case 4:
1154
+ if (g.rng.oneIn(3)) {
1155
+ for (let y = y1b; y <= y2b; y++) {
1156
+ if (y === centre.y) continue;
1157
+ setMarkedGranite(c, loc(x1a - 1, y), SQUARE.WALL_INNER);
1158
+ setMarkedGranite(c, loc(x2a + 1, y), SQUARE.WALL_INNER);
1159
+ }
1160
+ for (let x = x1a; x <= x2a; x++) {
1161
+ if (x === centre.x) continue;
1162
+ setMarkedGranite(c, loc(x, y1b - 1), SQUARE.WALL_INNER);
1163
+ setMarkedGranite(c, loc(x, y2b + 1), SQUARE.WALL_INNER);
1164
+ }
1165
+ if (g.rng.oneIn(3)) generateOpen(c, y1b - 1, x1a - 1, y2b + 1, x2a + 1, FEAT.CLOSED);
1166
+ } else if (g.rng.oneIn(3)) {
1167
+ generatePlus(c, y1b, x1a, y2b, x2a, FEAT.GRANITE, SQUARE.WALL_INNER);
1168
+ } else if (g.rng.oneIn(3)) {
1169
+ setMarkedGranite(c, centre, SQUARE.WALL_INNER);
1170
+ }
1171
+ break;
1172
+ }
1173
+ return true;
1174
+ }
1175
+
1176
+ function buildLarge(g: Gen, centreIn: Loc, _rating: number): boolean {
1177
+ const c = g.c;
1178
+ const height = 9;
1179
+ const width = 23;
1180
+ const light = c.depth <= g.rng.randint1(25);
1181
+ let centre = centreIn;
1182
+ if (centre.y >= c.height || centre.x >= c.width) {
1183
+ const found = findSpace(g, height + 2, width + 2);
1184
+ if (!found) return false;
1185
+ centre = found;
1186
+ }
1187
+ let y1 = centre.y - Math.trunc(height / 2);
1188
+ let y2 = centre.y + Math.trunc(height / 2);
1189
+ let x1 = centre.x - Math.trunc(width / 2);
1190
+ let x2 = centre.x + Math.trunc(width / 2);
1191
+
1192
+ generateRoom(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, light);
1193
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1194
+ fillRectangle(c, y1, x1, y2, x2, FEAT.FLOOR, SQUARE.NONE);
1195
+
1196
+ y1 = y1 + 2;
1197
+ y2 = y2 - 2;
1198
+ x1 = x1 + 2;
1199
+ x2 = x2 - 2;
1200
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1201
+
1202
+ switch (g.rng.randint1(5)) {
1203
+ case 1:
1204
+ generateHole(g.rng, c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.CLOSED);
1205
+ vaultMonsters(g, centre, c.depth + 2, 1);
1206
+ break;
1207
+ case 2: {
1208
+ generateHole(g.rng, c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.CLOSED);
1209
+ drawRectangle(c, centre.y - 1, centre.x - 1, centre.y + 1, centre.x + 1, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1210
+ generateHole(g.rng, c, centre.y - 1, centre.x - 1, centre.y + 1, centre.x + 1, FEAT.CLOSED);
1211
+ for (let y = centre.y - 1; y <= centre.y + 1; y++) {
1212
+ for (let x = centre.x - 1; x <= centre.x + 1; x++) {
1213
+ if (c.isClosedDoor(loc(x, y))) g.rng.randint1(7);
1214
+ }
1215
+ }
1216
+ vaultMonsters(g, centre, c.depth + 2, g.rng.randint1(3) + 2);
1217
+ if (g.rng.randint0(100) < 80 || g.dun.persist) {
1218
+ /* build_large case 2 (gen-room.c L2472): ORIGIN_SPECIAL. */
1219
+ placeObject(g, centre, c.depth, false, false, 0, ORIGIN.SPECIAL);
1220
+ } else {
1221
+ placeRandomStairs(g, centre, g.dun.quest);
1222
+ }
1223
+ vaultTraps(g, centre, 4, 10, 2 + g.rng.randint1(3));
1224
+ break;
1225
+ }
1226
+ case 3: {
1227
+ generateHole(g.rng, c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.CLOSED);
1228
+ fillRectangle(c, centre.y - 1, centre.x - 1, centre.y + 1, centre.x + 1, FEAT.GRANITE, SQUARE.WALL_INNER);
1229
+ if (g.rng.oneIn(2)) {
1230
+ if (g.rng.oneIn(2)) {
1231
+ fillRectangle(c, centre.y - 1, centre.x - 7, centre.y + 1, centre.x - 5, FEAT.GRANITE, SQUARE.WALL_INNER);
1232
+ fillRectangle(c, centre.y - 1, centre.x + 5, centre.y + 1, centre.x + 7, FEAT.GRANITE, SQUARE.WALL_INNER);
1233
+ } else {
1234
+ fillRectangle(c, centre.y - 1, centre.x - 6, centre.y + 1, centre.x - 4, FEAT.GRANITE, SQUARE.WALL_INNER);
1235
+ fillRectangle(c, centre.y - 1, centre.x + 4, centre.y + 1, centre.x + 6, FEAT.GRANITE, SQUARE.WALL_INNER);
1236
+ }
1237
+ }
1238
+ if (g.rng.oneIn(3)) {
1239
+ drawRectangle(c, centre.y - 1, centre.x - 5, centre.y + 1, centre.x + 5, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1240
+ placeSecretDoor(c, loc(centre.x - 3, centre.y - 3 + g.rng.randint1(2) * 2));
1241
+ placeSecretDoor(c, loc(centre.x + 3, centre.y - 3 + g.rng.randint1(2) * 2));
1242
+ vaultMonsters(g, loc(centre.x - 2, centre.y), c.depth + 2, g.rng.randint1(2));
1243
+ vaultMonsters(g, loc(centre.x + 2, centre.y), c.depth + 2, g.rng.randint1(2));
1244
+ /* build_large case 3 (gen-room.c L2531/L2534): ORIGIN_SPECIAL. */
1245
+ if (g.rng.oneIn(3)) placeObject(g, loc(centre.x - 2, centre.y), c.depth, false, false, 0, ORIGIN.SPECIAL);
1246
+ if (g.rng.oneIn(3)) placeObject(g, loc(centre.x + 2, centre.y), c.depth, false, false, 0, ORIGIN.SPECIAL);
1247
+ }
1248
+ break;
1249
+ }
1250
+ case 4: {
1251
+ generateHole(g.rng, c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.CLOSED);
1252
+ for (let y = y1; y <= y2; y++) {
1253
+ for (let x = x1; x <= x2; x++) {
1254
+ if ((x + y) & 0x01) setMarkedGranite(c, loc(x, y), SQUARE.WALL_INNER);
1255
+ }
1256
+ }
1257
+ vaultMonsters(g, loc(centre.x - 5, centre.y), c.depth + 2, g.rng.randint1(3));
1258
+ vaultMonsters(g, loc(centre.x + 5, centre.y), c.depth + 2, g.rng.randint1(3));
1259
+ vaultTraps(g, loc(centre.x - 3, centre.y), 2, 8, g.rng.randint1(3));
1260
+ vaultTraps(g, loc(centre.x + 3, centre.y), 2, 8, g.rng.randint1(3));
1261
+ vaultObjects(g, centre, c.depth, 3);
1262
+ break;
1263
+ }
1264
+ case 5: {
1265
+ generatePlus(c, y1, x1, y2, x2, FEAT.GRANITE, SQUARE.WALL_INNER);
1266
+ if (g.rng.randint0(100) < 50) {
1267
+ const i = g.rng.randint1(10);
1268
+ placeClosedDoor(g, loc(centre.x - i, y1 - 1));
1269
+ placeClosedDoor(g, loc(centre.x + i, y1 - 1));
1270
+ placeClosedDoor(g, loc(centre.x - i, y2 + 1));
1271
+ placeClosedDoor(g, loc(centre.x + i, y2 + 1));
1272
+ } else {
1273
+ const i = g.rng.randint1(3);
1274
+ placeClosedDoor(g, loc(x1 - 1, centre.y + i));
1275
+ placeClosedDoor(g, loc(x1 - 1, centre.y - i));
1276
+ placeClosedDoor(g, loc(x2 + 1, centre.y + i));
1277
+ placeClosedDoor(g, loc(x2 + 1, centre.y - i));
1278
+ }
1279
+ vaultObjects(g, centre, c.depth, 2 + g.rng.randint1(2));
1280
+ vaultMonsters(g, loc(centre.x - 4, centre.y + 1), c.depth + 2, g.rng.randint1(4));
1281
+ vaultMonsters(g, loc(centre.x + 4, centre.y + 1), c.depth + 2, g.rng.randint1(4));
1282
+ vaultMonsters(g, loc(centre.x - 4, centre.y - 1), c.depth + 2, g.rng.randint1(4));
1283
+ vaultMonsters(g, loc(centre.x + 4, centre.y - 1), c.depth + 2, g.rng.randint1(4));
1284
+ break;
1285
+ }
1286
+ }
1287
+ return true;
1288
+ }
1289
+
1290
+ /* ------------------------------------------------------------------ *
1291
+ * Nest / pit (faithful themed monster generation, gen-room.c).
1292
+ * ------------------------------------------------------------------ */
1293
+
1294
+ /**
1295
+ * build_nest (gen-room.c L2641): a rectangular moat around a room filled with
1296
+ * a DISORDERED scatter of monsters drawn from 64 pit-hooked picks. Nests never
1297
+ * contain uniques (mon_pit_hook rejects them).
1298
+ */
1299
+ function buildNest(g: Gen, centreIn: Loc, _rating: number): boolean {
1300
+ const c = g.c;
1301
+ if (!g.monDeps || !g.monDeps.pits) return false;
1302
+ const table = g.monDeps.table;
1303
+ const pits = g.monDeps.pits;
1304
+
1305
+ const sizeVary = g.rng.randint0(4);
1306
+ const height = 9;
1307
+ const width = 11 + 2 * sizeVary;
1308
+
1309
+ let centre = centreIn;
1310
+ if (centre.y >= c.height || centre.x >= c.width) {
1311
+ const found = findSpace(g, height + 2, width + 2);
1312
+ if (!found) return false;
1313
+ centre = found;
1314
+ }
1315
+
1316
+ let y1 = centre.y - Math.trunc(height / 2);
1317
+ let y2 = centre.y + Math.trunc(height / 2);
1318
+ let x1 = centre.x - Math.trunc(width / 2);
1319
+ let x2 = centre.x + Math.trunc(width / 2);
1320
+
1321
+ generateRoom(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, false);
1322
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1323
+ fillRectangle(c, y1, x1, y2, x2, FEAT.FLOOR, SQUARE.NONE);
1324
+
1325
+ /* Advance to the center room. */
1326
+ y1 = y1 + 2;
1327
+ y2 = y2 - 2;
1328
+ x1 = x1 + 2;
1329
+ x2 = x2 - 2;
1330
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1331
+ generateHole(g.rng, c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.CLOSED);
1332
+
1333
+ /* Decide on the pit type (nests are room type 2). */
1334
+ g.pitTelemetry.attempts.nest++;
1335
+ const pit = setPitType(g.rng, pits, c.depth, 2);
1336
+ g.pitTelemetry.selected.nest[pit.name] =
1337
+ (g.pitTelemetry.selected.nest[pit.name] ?? 0) + 1;
1338
+ const allocObj = pit.objRarity;
1339
+
1340
+ /* Prepare allocation table; pick 64 (hard) monster types. */
1341
+ table.prep(monPitHook(pit));
1342
+ const what: (MonsterRace | null)[] = [];
1343
+ let empty = false;
1344
+ for (let i = 0; i < 64; i++) {
1345
+ what[i] = table.getMonNum(g.rng, c.depth + 10, c.depth, g.uniquePlaced);
1346
+ if (!what[i]) empty = true;
1347
+ }
1348
+ table.prep(null);
1349
+ if (empty) {
1350
+ g.pitTelemetry.empty.nest++;
1351
+ return false;
1352
+ }
1353
+
1354
+ /* Increase the level rating (gen-room.c L2718). */
1355
+ c.addToMonsterRating(sizeVary + Math.trunc(pit.ave / 20));
1356
+
1357
+ /* Place some monsters (disordered scatter) and occasional objects. */
1358
+ const info: MonsterGroupInfo = { index: 0, role: MON_GROUP.LEADER };
1359
+ for (let y = y1; y <= y2; y++) {
1360
+ for (let x = x1; x <= x2; x++) {
1361
+ const race = what[g.rng.randint0(64)] as MonsterRace;
1362
+ placeNewMonster(g, loc(x, y), race, false, false, info, ORIGIN.DROP_PIT);
1363
+
1364
+ /* Occasionally place an item, making it good 1/3 of the time. */
1365
+ if (g.rng.randint0(100) < allocObj) {
1366
+ /* build_nest/build_pit (gen-room.c L2730/L2957): ORIGIN_PIT. */
1367
+ placeObject(g, loc(x, y), c.depth + 10, g.rng.oneIn(3), false, 0, ORIGIN.PIT);
1368
+ }
1369
+ }
1370
+ }
1371
+ return true;
1372
+ }
1373
+
1374
+ /**
1375
+ * build_pit (gen-room.c L2773): an ORDERED pit. 16 pit-hooked monsters are
1376
+ * drawn, bubble-sorted by level, and the even entries used to fill the fixed
1377
+ * concentric/mirrored pattern (what[7] centre, radiating out to what[0]).
1378
+ * Pits never contain uniques.
1379
+ *
1380
+ * #############
1381
+ * #11000000011#
1382
+ * #01234543210#
1383
+ * #01236763210#
1384
+ * #01234543210#
1385
+ * #11000000011#
1386
+ * #############
1387
+ */
1388
+ function buildPit(g: Gen, centreIn: Loc, _rating: number): boolean {
1389
+ const c = g.c;
1390
+ if (!g.monDeps || !g.monDeps.pits) return false;
1391
+ const table = g.monDeps.table;
1392
+ const pits = g.monDeps.pits;
1393
+
1394
+ const height = 9;
1395
+ const width = 15;
1396
+
1397
+ let centre = centreIn;
1398
+ if (centre.y >= c.height || centre.x >= c.width) {
1399
+ const found = findSpace(g, height + 2, width + 2);
1400
+ if (!found) return false;
1401
+ centre = found;
1402
+ }
1403
+
1404
+ let y1 = centre.y - Math.trunc(height / 2);
1405
+ let y2 = centre.y + Math.trunc(height / 2);
1406
+ let x1 = centre.x - Math.trunc(width / 2);
1407
+ let x2 = centre.x + Math.trunc(width / 2);
1408
+
1409
+ generateRoom(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, false);
1410
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_OUTER, false);
1411
+ fillRectangle(c, y1, x1, y2, x2, FEAT.FLOOR, SQUARE.NONE);
1412
+
1413
+ /* Advance to the center room. */
1414
+ y1 = y1 + 2;
1415
+ y2 = y2 - 2;
1416
+ x1 = x1 + 2;
1417
+ x2 = x2 - 2;
1418
+ drawRectangle(c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.GRANITE, SQUARE.WALL_INNER, false);
1419
+ generateHole(g.rng, c, y1 - 1, x1 - 1, y2 + 1, x2 + 1, FEAT.CLOSED);
1420
+
1421
+ /* Decide on the pit type (pits are room type 1). */
1422
+ g.pitTelemetry.attempts.pit++;
1423
+ const pit = setPitType(g.rng, pits, c.depth, 1);
1424
+ g.pitTelemetry.selected.pit[pit.name] =
1425
+ (g.pitTelemetry.selected.pit[pit.name] ?? 0) + 1;
1426
+ const allocObj = pit.objRarity;
1427
+
1428
+ /* Prepare allocation table; pick 16 (hard) monster types. */
1429
+ table.prep(monPitHook(pit));
1430
+ const what: (MonsterRace | null)[] = [];
1431
+ let empty = false;
1432
+ for (let i = 0; i < 16; i++) {
1433
+ what[i] = table.getMonNum(g.rng, c.depth + 10, c.depth, g.uniquePlaced);
1434
+ if (!what[i]) empty = true;
1435
+ }
1436
+ table.prep(null);
1437
+ if (empty) {
1438
+ g.pitTelemetry.empty.pit++;
1439
+ return false;
1440
+ }
1441
+
1442
+ /* Sort the 16 entries by level (bubble sort, stable on ties). */
1443
+ const sorted = what as MonsterRace[];
1444
+ for (let i = 0; i < 16 - 1; i++) {
1445
+ for (let j = 0; j < 16 - 1; j++) {
1446
+ const a = sorted[j] as MonsterRace;
1447
+ const b = sorted[j + 1] as MonsterRace;
1448
+ if (a.level > b.level) {
1449
+ sorted[j] = b;
1450
+ sorted[j + 1] = a;
1451
+ }
1452
+ }
1453
+ }
1454
+
1455
+ /* Select every other entry (the even-indexed picks). */
1456
+ const pick: MonsterRace[] = [];
1457
+ for (let i = 0; i < 8; i++) pick[i] = sorted[i * 2] as MonsterRace;
1458
+
1459
+ /* Increase the level rating (gen-room.c L2867). */
1460
+ c.addToMonsterRating(3 + Math.trunc(pit.ave / 20));
1461
+
1462
+ /* Fixed concentric placement. Center monster is the group leader. */
1463
+ const groupIndex = g.nextGroupIndex();
1464
+ const cx = centre.x;
1465
+ const cy = centre.y;
1466
+ const leader: MonsterGroupInfo = { index: groupIndex, role: MON_GROUP.LEADER };
1467
+ /* build_pit centre (gen-room.c L2875): ORIGIN_DROP_PIT. */
1468
+ placeNewMonster(g, centre, pick[7] as MonsterRace, false, false, leader, ORIGIN.DROP_PIT);
1469
+
1470
+ /* Remaining monsters are servants. */
1471
+ const info: MonsterGroupInfo = { index: groupIndex, role: MON_GROUP.SERVANT };
1472
+
1473
+ /* Top and bottom rows (middle). */
1474
+ for (let x = cx - 3; x <= cx + 3; x++) {
1475
+ placeNewMonster(g, loc(x, cy - 2), pick[0] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1476
+ placeNewMonster(g, loc(x, cy + 2), pick[0] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1477
+ }
1478
+
1479
+ /* Corners. */
1480
+ for (let x = cx - 5; x <= cx - 4; x++) {
1481
+ placeNewMonster(g, loc(x, cy - 2), pick[1] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1482
+ placeNewMonster(g, loc(x, cy + 2), pick[1] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1483
+ }
1484
+ for (let x = cx + 4; x <= cx + 5; x++) {
1485
+ placeNewMonster(g, loc(x, cy - 2), pick[1] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1486
+ placeNewMonster(g, loc(x, cy + 2), pick[1] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1487
+ }
1488
+
1489
+ /* Middle columns. */
1490
+ for (let y = cy - 1; y <= cy + 1; y++) {
1491
+ placeNewMonster(g, loc(cx - 5, y), pick[0] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1492
+ placeNewMonster(g, loc(cx + 5, y), pick[0] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1493
+
1494
+ placeNewMonster(g, loc(cx - 4, y), pick[1] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1495
+ placeNewMonster(g, loc(cx + 4, y), pick[1] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1496
+
1497
+ placeNewMonster(g, loc(cx - 3, y), pick[2] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1498
+ placeNewMonster(g, loc(cx + 3, y), pick[2] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1499
+
1500
+ placeNewMonster(g, loc(cx - 2, y), pick[3] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1501
+ placeNewMonster(g, loc(cx + 2, y), pick[3] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1502
+ }
1503
+
1504
+ /* Corners around the middle monster. */
1505
+ placeNewMonster(g, loc(cx - 1, cy - 1), pick[4] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1506
+ placeNewMonster(g, loc(cx + 1, cy - 1), pick[4] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1507
+ placeNewMonster(g, loc(cx - 1, cy + 1), pick[4] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1508
+ placeNewMonster(g, loc(cx + 1, cy + 1), pick[4] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1509
+
1510
+ /* Above/below the center monster. */
1511
+ for (let x = cx - 1; x <= cx + 1; x++) {
1512
+ placeNewMonster(g, loc(x, cy + 1), pick[5] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1513
+ placeNewMonster(g, loc(x, cy - 1), pick[5] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1514
+ }
1515
+
1516
+ /* Next to the center monster. */
1517
+ placeNewMonster(g, loc(cx + 1, cy), pick[6] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1518
+ placeNewMonster(g, loc(cx - 1, cy), pick[6] as MonsterRace, false, false, info, ORIGIN.DROP_PIT);
1519
+
1520
+ /* Place some objects. */
1521
+ for (let y = cy - 2; y <= cy + 2; y++) {
1522
+ for (let x = cx - 9; x <= cx + 9; x++) {
1523
+ if (g.rng.randint0(100) < allocObj) {
1524
+ /* build_nest/build_pit (gen-room.c L2730/L2957): ORIGIN_PIT. */
1525
+ placeObject(g, loc(x, y), c.depth + 10, g.rng.oneIn(3), false, 0, ORIGIN.PIT);
1526
+ }
1527
+ }
1528
+ }
1529
+ return true;
1530
+ }
1531
+
1532
+ /* ------------------------------------------------------------------ *
1533
+ * Moria / room of chambers / huge (starburst + cellular builders).
1534
+ * ------------------------------------------------------------------ */
1535
+
1536
+ /**
1537
+ * build_moria (gen-room.c L3138): a moria-style starburst cave room, sometimes
1538
+ * enlarged, sometimes long and narrow, occasionally sprinkled with rubble.
1539
+ *
1540
+ * RNG order (verified against gen-room.c L3138-3209):
1541
+ * randint1(35) [light], randint0(5) [height], randint0(5) [width];
1542
+ * the two-try space loop: per try one_in_(15) [large], else one_in_(4)
1543
+ * and (when !one_in_(4)) one_in_(15) + randint0(2)/randint0(3) [stretch];
1544
+ * generate_starburst_room; one_in_(10) [rubble] then 4x randint0(dim/4).
1545
+ */
1546
+ function buildMoria(g: Gen, centreIn: Loc, _rating: number): boolean {
1547
+ const c = g.c;
1548
+ const light = c.depth <= g.rng.randint1(35);
1549
+
1550
+ /* Pick a room size. */
1551
+ let height = 8 + g.rng.randint0(5);
1552
+ let width = 10 + g.rng.randint0(5);
1553
+
1554
+ let centre = centreIn;
1555
+ let placed = false;
1556
+
1557
+ /* Try twice to find space for a room. */
1558
+ for (let i = 0; i < 2; i++) {
1559
+ /* Really large room - only on first try. */
1560
+ if (i === 0 && g.rng.oneIn(15)) {
1561
+ height *= 1 + g.rng.randint1(2);
1562
+ width *= 2 + g.rng.randint1(3);
1563
+ } else if (!g.rng.oneIn(4)) {
1564
+ /* Long, narrow room. Sometimes tall and thin. */
1565
+ if (g.rng.oneIn(15)) height *= 2 + g.rng.randint0(2);
1566
+ else width *= 2 + g.rng.randint0(3);
1567
+ }
1568
+
1569
+ /* Find and reserve some space in the dungeon. Get center of room. */
1570
+ if (centre.y >= c.height || centre.x >= c.width) {
1571
+ const found = findSpace(g, height, width);
1572
+ if (!found) {
1573
+ if (i === 0) continue; /* Failed first attempt */
1574
+ if (i === 1) return false; /* Failed second attempt */
1575
+ } else {
1576
+ centre = found;
1577
+ placed = true;
1578
+ break; /* Success */
1579
+ }
1580
+ } else {
1581
+ placed = true;
1582
+ break; /* Not finding space */
1583
+ }
1584
+ }
1585
+ if (!placed) return false;
1586
+
1587
+ /* Locate the room. */
1588
+ const y1 = centre.y - Math.trunc(height / 2);
1589
+ const x1 = centre.x - Math.trunc(width / 2);
1590
+ const y2 = y1 + height - 1;
1591
+ const x2 = x1 + width - 1;
1592
+
1593
+ /* Generate starburst room. Return immediately if out of bounds. */
1594
+ if (!generateStarburstRoom(g, y1, x1, y2, x2, light, FEAT.FLOOR, true)) {
1595
+ return false;
1596
+ }
1597
+
1598
+ /* Sometimes, the room may have rubble in it. */
1599
+ if (g.rng.oneIn(10)) {
1600
+ generateStarburstRoom(
1601
+ g,
1602
+ y1 + g.rng.randint0(Math.trunc(height / 4)),
1603
+ x1 + g.rng.randint0(Math.trunc(width / 4)),
1604
+ y2 - g.rng.randint0(Math.trunc(height / 4)),
1605
+ x2 - g.rng.randint0(Math.trunc(width / 4)),
1606
+ false,
1607
+ FEAT.PASS_RUBBLE,
1608
+ false,
1609
+ );
1610
+ }
1611
+
1612
+ return true;
1613
+ }
1614
+
1615
+ /**
1616
+ * make_inner_chamber_wall (gen-room.c L1739): mark a granite/magma grid that is
1617
+ * not already an outer/solid wall as an inner wall. NEW carving helper.
1618
+ */
1619
+ function makeInnerChamberWall(c: Chunk, y: number, x: number): void {
1620
+ const grid = loc(x, y);
1621
+ const feat = c.feat(grid);
1622
+ if (feat !== FEAT.GRANITE && feat !== FEAT.MAGMA) return;
1623
+ if (c.isWallOuter(grid)) return;
1624
+ if (c.isWallSolid(grid)) return;
1625
+ setMarkedGranite(c, grid, SQUARE.WALL_INNER);
1626
+ }
1627
+
1628
+ /**
1629
+ * make_chamber (gen-room.c L1761): fill a rectangle with magma, wrap it in
1630
+ * inner wall, and punch one door into a random border grid (up to 20 tries).
1631
+ * NEW carving helper. RNG: per door try one_in_(2) [axis], one_in_(2) [side],
1632
+ * randint0(1 + span) [position].
1633
+ */
1634
+ function makeChamber(
1635
+ g: Gen,
1636
+ y1: number,
1637
+ x1: number,
1638
+ y2: number,
1639
+ x2: number,
1640
+ ): void {
1641
+ const c = g.c;
1642
+
1643
+ /* Fill with soft granite (will later be replaced with floor). */
1644
+ fillRectangle(c, y1 + 1, x1 + 1, y2 - 1, x2 - 1, FEAT.MAGMA, SQUARE.NONE);
1645
+
1646
+ /* Generate inner walls over dungeon granite and magma. */
1647
+ for (let y = y1; y <= y2; y++) {
1648
+ makeInnerChamberWall(c, y, x1);
1649
+ makeInnerChamberWall(c, y, x2);
1650
+ }
1651
+ for (let x = x1; x <= x2; x++) {
1652
+ makeInnerChamberWall(c, y1, x);
1653
+ makeInnerChamberWall(c, y2, x);
1654
+ }
1655
+
1656
+ /* Try a few times to place a door. */
1657
+ for (let i = 0; i < 20; i++) {
1658
+ let x: number;
1659
+ let y: number;
1660
+ /* Pick a square along the edge, not a corner. */
1661
+ if (g.rng.oneIn(2)) {
1662
+ x = g.rng.oneIn(2) ? x1 : x2;
1663
+ y = y1 + g.rng.randint0(1 + Math.abs(y2 - y1));
1664
+ } else {
1665
+ y = g.rng.oneIn(2) ? y1 : y2;
1666
+ x = x1 + g.rng.randint0(1 + Math.abs(x2 - x1));
1667
+ }
1668
+
1669
+ /* If not an inner wall square, try again. */
1670
+ if (!c.isWallInner(loc(x, y))) continue;
1671
+
1672
+ /* Paranoia */
1673
+ if (!c.inBoundsFully(loc(x, y))) continue;
1674
+
1675
+ /* Reset wall count */
1676
+ let count = 0;
1677
+
1678
+ /*
1679
+ * If square has not more than two adjacent walls, and no adjacent
1680
+ * doors, place door.
1681
+ */
1682
+ for (let d = 0; d < 9; d++) {
1683
+ const off = DDGRID_DDD[d] as Loc;
1684
+ const adj = loc(x + off.x, y + off.y);
1685
+
1686
+ /* No doors beside doors. */
1687
+ if (c.feat(adj) === FEAT.OPEN) break;
1688
+
1689
+ /* Count the inner walls. */
1690
+ if (c.isWallInner(adj)) count++;
1691
+
1692
+ /* No more than two walls adjacent (plus the one we're on). */
1693
+ if (count > 3) break;
1694
+
1695
+ /* Checked every direction? */
1696
+ if (d === 8) {
1697
+ /* Place an open door. */
1698
+ c.setFeat(loc(x, y), FEAT.OPEN);
1699
+ return;
1700
+ }
1701
+ }
1702
+ }
1703
+ }
1704
+
1705
+ /**
1706
+ * hollow_out_room (gen-room.c L1846): flood-fill from a start grid, turning
1707
+ * adjacent magma into floor and adjacent open doors into broken doors, then
1708
+ * recursing. NEW carving helper. No RNG.
1709
+ */
1710
+ function hollowOutRoom(c: Chunk, grid: Loc): void {
1711
+ for (let d = 0; d < 9; d++) {
1712
+ const off = DDGRID_DDD[d] as Loc;
1713
+ const g1 = loc(grid.x + off.x, grid.y + off.y);
1714
+ const feat = c.feat(g1);
1715
+ if (feat === FEAT.MAGMA) {
1716
+ c.setFeat(g1, FEAT.FLOOR);
1717
+ hollowOutRoom(c, g1);
1718
+ } else if (feat === FEAT.OPEN) {
1719
+ c.setFeat(g1, FEAT.BROKEN);
1720
+ hollowOutRoom(c, g1);
1721
+ }
1722
+ }
1723
+ }
1724
+
1725
+ /**
1726
+ * build_room_of_chambers (gen-room.c L3239): a large room subdivided into many
1727
+ * irregular magma chambers, hollowed out and connected by doors/tunnels, then
1728
+ * filled with themed monsters via get_chamber_monsters.
1729
+ *
1730
+ * RNG order (verified against gen-room.c L3239-3517):
1731
+ * randint0(45) [light], m_bonus(20,depth) [height], randint1(20) +
1732
+ * m_bonus(20,depth) [width]; find_space when needed; per chamber
1733
+ * randint0(4)+randint0(10)+randint0(4) [size] and 2x randint0 [corner] then
1734
+ * make_chamber; the deterministic door/hollow/wall cleanup passes (magma
1735
+ * spot loop draws 2x randint0 per try); place_random_door on broken doors;
1736
+ * finally get_chamber_monsters.
1737
+ */
1738
+ function buildRoomOfChambers(g: Gen, centreIn: Loc, _rating: number): boolean {
1739
+ const c = g.c;
1740
+
1741
+ /* Deeper in the dungeon, chambers are less likely to be lit. */
1742
+ const light = g.rng.randint0(45) > c.depth;
1743
+
1744
+ /* Calculate a level-dependent room size. */
1745
+ const height = 20 + g.rng.mBonus(20, c.depth);
1746
+ const width = 20 + g.rng.randint1(20) + g.rng.mBonus(20, c.depth);
1747
+
1748
+ /* Find and reserve some space in the dungeon. Get center of room. */
1749
+ let centre = centreIn;
1750
+ if (centre.y >= c.height || centre.x >= c.width) {
1751
+ const found = findSpace(g, height, width);
1752
+ if (!found) return false;
1753
+ centre = found;
1754
+ }
1755
+
1756
+ /* Calculate the borders of the room. */
1757
+ const y1 = centre.y - Math.trunc(height / 2);
1758
+ const x1 = centre.x - Math.trunc(width / 2);
1759
+ const y2 = centre.y + Math.trunc((height - 1) / 2);
1760
+ const x2 = centre.x + Math.trunc((width - 1) / 2);
1761
+
1762
+ /* Make certain the room does not cross the dungeon edge. */
1763
+ if (!c.inBounds(loc(x1, y1)) || !c.inBounds(loc(x2, y2))) return false;
1764
+
1765
+ /* Determine how much space we have. */
1766
+ const area = Math.abs(y2 - y1) * Math.abs(x2 - x1);
1767
+
1768
+ /* Calculate the number of smaller chambers to make. */
1769
+ const numChambers = 10 + Math.trunc(area / 80);
1770
+
1771
+ /* Build the chambers. */
1772
+ for (let i = 0; i < numChambers; i++) {
1773
+ /* Determine size of chamber. */
1774
+ const size = 3 + g.rng.randint0(4);
1775
+ const widthLocal = size + g.rng.randint0(10);
1776
+ const heightLocal = size + g.rng.randint0(4);
1777
+
1778
+ /* Pick an upper-left corner at random. */
1779
+ const cY1 = y1 + g.rng.randint0(1 + y2 - y1 - heightLocal);
1780
+ const cX1 = x1 + g.rng.randint0(1 + x2 - x1 - widthLocal);
1781
+
1782
+ /* Determine lower-right corner of chamber. */
1783
+ let cY2 = cY1 + heightLocal;
1784
+ if (cY2 > y2) cY2 = y2;
1785
+ let cX2 = cX1 + widthLocal;
1786
+ if (cX2 > x2) cX2 = x2;
1787
+
1788
+ /* Make me a (magma filled) chamber. */
1789
+ makeChamber(g, cY1, cX1, cY2, cX2);
1790
+ }
1791
+
1792
+ /* Remove useless doors, fill in tiny, narrow rooms. */
1793
+ for (let gy = y1; gy <= y2; gy++) {
1794
+ for (let gx = x1; gx <= x2; gx++) {
1795
+ const grid = loc(gx, gy);
1796
+ let count = 0;
1797
+
1798
+ /* Stay legal. */
1799
+ if (!c.inBoundsFully(grid)) continue;
1800
+
1801
+ /* Check all adjacent grids. */
1802
+ for (let d = 0; d < 8; d++) {
1803
+ const off = DDGRID_DDD[d] as Loc;
1804
+ const grid1 = loc(gx + off.x, gy + off.y);
1805
+ /* Count the walls and dungeon granite. */
1806
+ if (
1807
+ c.feat(grid1) === FEAT.GRANITE &&
1808
+ !c.isWallOuter(grid1) &&
1809
+ !c.isWallSolid(grid1)
1810
+ ) {
1811
+ count++;
1812
+ }
1813
+ }
1814
+
1815
+ /* Five adjacent walls: Change non-chamber to wall. */
1816
+ if (count === 5 && c.feat(grid) !== FEAT.MAGMA) {
1817
+ setMarkedGranite(c, grid, SQUARE.WALL_INNER);
1818
+ } else if (count > 5) {
1819
+ /* More than five adjacent walls: Change anything to wall. */
1820
+ setMarkedGranite(c, grid, SQUARE.WALL_INNER);
1821
+ }
1822
+ }
1823
+ }
1824
+
1825
+ /* Pick a random magma spot near the center of the room. */
1826
+ let spot = loc(x1, y1);
1827
+ for (let i = 0; i < 50; i++) {
1828
+ spot = loc(
1829
+ x1 + Math.trunc(Math.abs(x2 - x1) / 4) + g.rng.randint0(Math.trunc(Math.abs(x2 - x1) / 2)),
1830
+ y1 + Math.trunc(Math.abs(y2 - y1) / 4) + g.rng.randint0(Math.trunc(Math.abs(y2 - y1) / 2)),
1831
+ );
1832
+ if (c.feat(spot) === FEAT.MAGMA) break;
1833
+ }
1834
+
1835
+ /* Hollow out the first room. */
1836
+ c.setFeat(spot, FEAT.FLOOR);
1837
+ hollowOutRoom(c, spot);
1838
+
1839
+ /* Attempt to change every in-room magma grid to open floor. */
1840
+ for (let iter = 0; iter < 100; iter++) {
1841
+ /* Assume this run will do no useful work. */
1842
+ let joy = false;
1843
+
1844
+ /* Make new doors and tunnels between magma and open floor. */
1845
+ for (let gy = y1; gy < y2; gy++) {
1846
+ for (let gx = x1; gx < x2; gx++) {
1847
+ const grid = loc(gx, gy);
1848
+ /* Current grid must be magma. */
1849
+ if (c.feat(grid) !== FEAT.MAGMA) continue;
1850
+
1851
+ /* Stay legal. */
1852
+ if (!c.inBoundsFully(grid)) continue;
1853
+
1854
+ /* Check only horizontal and vertical directions. */
1855
+ for (let d = 0; d < 4; d++) {
1856
+ const off = DDGRID_DDD[d] as Loc;
1857
+ const grid1 = loc(gx + off.x, gy + off.y);
1858
+
1859
+ /* Need inner wall. */
1860
+ if (!c.isWallInner(grid1)) continue;
1861
+
1862
+ /* Keep going in the same direction, if in bounds. */
1863
+ const grid2 = loc(grid1.x + off.x, grid1.y + off.y);
1864
+ if (!c.inBounds(grid2)) continue;
1865
+
1866
+ /* If we find open floor, place a door. */
1867
+ if (c.feat(grid2) === FEAT.FLOOR) {
1868
+ joy = true;
1869
+
1870
+ /* Make a broken door in the wall grid. */
1871
+ c.setFeat(grid1, FEAT.BROKEN);
1872
+
1873
+ /* Hollow out the new room. */
1874
+ c.setFeat(grid, FEAT.FLOOR);
1875
+ hollowOutRoom(c, grid);
1876
+
1877
+ break;
1878
+ }
1879
+
1880
+ /* If we find more inner wall... */
1881
+ if (c.isWallInner(grid2)) {
1882
+ /* ...Keep going in the same direction. */
1883
+ const grid3 = loc(grid2.x + off.x, grid2.y + off.y);
1884
+ if (!c.inBounds(grid3)) continue;
1885
+
1886
+ /* If we /now/ find floor, make a tunnel. */
1887
+ if (c.feat(grid3) === FEAT.FLOOR) {
1888
+ joy = true;
1889
+
1890
+ /* Turn both wall grids into floor. */
1891
+ c.setFeat(grid1, FEAT.FLOOR);
1892
+ c.setFeat(grid2, FEAT.FLOOR);
1893
+
1894
+ /* Hollow out the new room. */
1895
+ c.setFeat(grid, FEAT.FLOOR);
1896
+ hollowOutRoom(c, grid);
1897
+
1898
+ break;
1899
+ }
1900
+ }
1901
+ }
1902
+ }
1903
+ }
1904
+
1905
+ /* If we could find no work to do, stop. */
1906
+ if (!joy) break;
1907
+ }
1908
+
1909
+ /* Turn broken doors into a random kind of door, remove open doors. */
1910
+ for (let gy = y1; gy <= y2; gy++) {
1911
+ for (let gx = x1; gx <= x2; gx++) {
1912
+ const grid = loc(gx, gy);
1913
+ if (c.feat(grid) === FEAT.OPEN) {
1914
+ setMarkedGranite(c, grid, SQUARE.WALL_INNER);
1915
+ } else if (c.feat(grid) === FEAT.BROKEN) {
1916
+ placeRandomDoor(g, grid);
1917
+ }
1918
+ }
1919
+ }
1920
+
1921
+ /*
1922
+ * Turn all walls and magma not adjacent to floor into dungeon granite.
1923
+ * Turn all floors and adjacent grids into rooms, sometimes lighting them.
1924
+ */
1925
+ {
1926
+ const gyStart = y1 - 1 > 0 ? y1 - 1 : 0;
1927
+ const gyEnd = y2 + 2 < c.height ? y2 + 2 : c.height;
1928
+ const gxStart = x1 - 1 > 0 ? x1 - 1 : 0;
1929
+ const gxEnd = x2 + 2 < c.width ? x2 + 2 : c.width;
1930
+ for (let gy = gyStart; gy < gyEnd; gy++) {
1931
+ for (let gx = gxStart; gx < gxEnd; gx++) {
1932
+ const grid = loc(gx, gy);
1933
+
1934
+ if (c.isWallInner(grid) || c.feat(grid) === FEAT.MAGMA) {
1935
+ for (let d = 0; d < 9; d++) {
1936
+ const off = DDGRID_DDD[d] as Loc;
1937
+ const grid1 = loc(gx + off.x, gy + off.y);
1938
+ /* Stay legal */
1939
+ if (!c.inBounds(grid1)) continue;
1940
+ /* No floors allowed */
1941
+ if (c.feat(grid1) === FEAT.FLOOR) break;
1942
+ /* Turn me into dungeon granite. */
1943
+ if (d === 8) setMarkedGranite(c, grid, SQUARE.NONE);
1944
+ }
1945
+ }
1946
+ if (c.isFloor(grid)) {
1947
+ for (let d = 0; d < 9; d++) {
1948
+ const off = DDGRID_DDD[d] as Loc;
1949
+ const grid1 = loc(gx + off.x, gy + off.y);
1950
+ /* Stay legal */
1951
+ if (!c.inBounds(grid1)) continue;
1952
+ /* Turn into room, forbid stairs. */
1953
+ c.sqinfoOn(grid1, SQUARE.ROOM);
1954
+ c.sqinfoOn(grid1, SQUARE.NO_STAIRS);
1955
+ /* Illuminate if requested. */
1956
+ if (light) c.sqinfoOn(grid1, SQUARE.GLOW);
1957
+ }
1958
+ }
1959
+ }
1960
+ }
1961
+
1962
+ /* Turn all inner wall grids adjacent to dungeon granite into outer walls. */
1963
+ for (let gy = gyStart; gy < gyEnd; gy++) {
1964
+ for (let gx = gxStart; gx < gxEnd; gx++) {
1965
+ const grid = loc(gx, gy);
1966
+ /* Stay legal. */
1967
+ if (!c.inBoundsFully(grid)) continue;
1968
+
1969
+ if (c.isWallInner(grid)) {
1970
+ for (let d = 0; d < 9; d++) {
1971
+ const off = DDGRID_DDD[d] as Loc;
1972
+ const grid1 = loc(gx + off.x, gy + off.y);
1973
+ /* Look for dungeon granite */
1974
+ if (
1975
+ c.feat(grid1) === FEAT.GRANITE &&
1976
+ !c.isWallInner(grid) &&
1977
+ !c.isWallOuter(grid) &&
1978
+ !c.isWallSolid(grid)
1979
+ ) {
1980
+ /* Turn me into outer wall. */
1981
+ setMarkedGranite(c, grid, SQUARE.WALL_OUTER);
1982
+ break;
1983
+ }
1984
+ }
1985
+ }
1986
+ }
1987
+ }
1988
+ }
1989
+
1990
+ /*** Now we get to place the monsters. ***/
1991
+ getChamberMonsters(g, y1, x1, y2, x2, height * width);
1992
+
1993
+ /* Increase the level rating. */
1994
+ c.addToMonsterRating(10);
1995
+
1996
+ return true;
1997
+ }
1998
+
1999
+ /**
2000
+ * build_huge (gen-room.c L3533): a single extreme-size starburst room, usually
2001
+ * broken up with irregular rubble fields. Only built as the first non-staircase
2002
+ * room, at a flat 5% chance.
2003
+ *
2004
+ * RNG order (verified against gen-room.c L3533-3605):
2005
+ * randint0(10) [height], randint0(50) [width]; the cent_n/nstair_room gate
2006
+ * (no RNG); one_in_(20) [5% gate]; one_in_(3) [light]; find_space when
2007
+ * needed; generate_starburst_room; randint1(5) [rubble gate] then
2008
+ * randint1(2) [count] and per field randint0(16)/randint0(24)/2x randint0.
2009
+ */
2010
+ function buildHuge(g: Gen, centreIn: Loc, _rating: number): boolean {
2011
+ const c = g.c;
2012
+ const dun = g.dun;
2013
+ const findingSpace = centreIn.y >= c.height || centreIn.x >= c.width;
2014
+
2015
+ const height = 30 + g.rng.randint0(10);
2016
+ const width = 45 + g.rng.randint0(50);
2017
+
2018
+ /*
2019
+ * Only try to build a huge room as the first non-staircase room. If not
2020
+ * finding space, cent_n has already been incremented.
2021
+ */
2022
+ if (dun.centN - dun.nstairRoom > (findingSpace ? 0 : 1)) return false;
2023
+
2024
+ /* Flat 5% chance. */
2025
+ if (!g.rng.oneIn(20)) return false;
2026
+
2027
+ /* This room is usually lit. */
2028
+ const light = !g.rng.oneIn(3);
2029
+
2030
+ /* Find and reserve some space. Get center of room. */
2031
+ let centre = centreIn;
2032
+ if (findingSpace) {
2033
+ const found = findSpace(g, height, width);
2034
+ if (!found) return false;
2035
+ centre = found;
2036
+ }
2037
+
2038
+ /* Locate the room. */
2039
+ const y1 = centre.y - Math.trunc(height / 2);
2040
+ const x1 = centre.x - Math.trunc(width / 2);
2041
+ const y2 = y1 + height - 1;
2042
+ const x2 = x1 + width - 1;
2043
+
2044
+ /* Make a huge starburst room with optional light. */
2045
+ if (!generateStarburstRoom(g, y1, x1, y2, x2, light, FEAT.FLOOR, false)) {
2046
+ return false;
2047
+ }
2048
+
2049
+ /* Often, add rubble to break things up a bit. */
2050
+ if (g.rng.randint1(5) > 2) {
2051
+ /* Determine how many rubble fields to add (between 1 and 6). */
2052
+ const count = Math.trunc((height * width * g.rng.randint1(2)) / 1100);
2053
+
2054
+ /* Make the rubble fields. */
2055
+ for (let i = 0; i < count; i++) {
2056
+ const heightTmp = 8 + g.rng.randint0(16);
2057
+ const widthTmp = 10 + g.rng.randint0(24);
2058
+
2059
+ /* Semi-random location. */
2060
+ const y1Tmp = y1 + g.rng.randint0(height - heightTmp);
2061
+ const x1Tmp = x1 + g.rng.randint0(width - widthTmp);
2062
+ const y2Tmp = y1Tmp + heightTmp;
2063
+ const x2Tmp = x1Tmp + widthTmp;
2064
+
2065
+ /* Make the rubble field. */
2066
+ generateStarburstRoom(
2067
+ g,
2068
+ y1Tmp,
2069
+ x1Tmp,
2070
+ y2Tmp,
2071
+ x2Tmp,
2072
+ false,
2073
+ FEAT.PASS_RUBBLE,
2074
+ false,
2075
+ );
2076
+ }
2077
+ }
2078
+
2079
+ return true;
2080
+ }
2081
+
2082
+ /* ------------------------------------------------------------------ *
2083
+ * Room profile + builder registry.
2084
+ * ------------------------------------------------------------------ */
2085
+
2086
+ /** A room entry in a dungeon profile's room list. */
2087
+ export interface RoomProfile {
2088
+ name: string;
2089
+ /** Registry key resolved from list-rooms.h. */
2090
+ builder: string;
2091
+ rating: number;
2092
+ height: number;
2093
+ width: number;
2094
+ level: number;
2095
+ pit: boolean;
2096
+ rarity: number;
2097
+ cutoff: number;
2098
+ }
2099
+
2100
+ export type RoomBuilder = (g: Gen, centre: Loc, rating: number) => boolean;
2101
+
2102
+ /** The runtime-registrable, string-keyed room builder registry. */
2103
+ export class RoomRegistry {
2104
+ private readonly map = new Map<string, RoomBuilder>();
2105
+
2106
+ constructor(private readonly data: RoomData) {}
2107
+
2108
+ /** The loaded vault list (used by hard_centre's vault_chunk). */
2109
+ get vaults(): Vault[] {
2110
+ return this.data.vaults;
2111
+ }
2112
+
2113
+ register(name: string, builder: RoomBuilder): void {
2114
+ this.map.set(name, builder);
2115
+ }
2116
+
2117
+ get(name: string): RoomBuilder {
2118
+ const b = this.map.get(name);
2119
+ if (!b) throw new Error(`gen: no room builder registered for '${name}'`);
2120
+ return b;
2121
+ }
2122
+
2123
+ has(name: string): boolean {
2124
+ return this.map.has(name);
2125
+ }
2126
+
2127
+ names(): string[] {
2128
+ return [...this.map.keys()];
2129
+ }
2130
+ }
2131
+
2132
+ /** Create a registry populated with the upstream builders bound to data. */
2133
+ export function createRoomRegistry(data: RoomData): RoomRegistry {
2134
+ const r = new RoomRegistry(data);
2135
+ r.register("staircase", buildStaircase);
2136
+ r.register("simple", buildSimple);
2137
+ r.register("circular", buildCircular);
2138
+ r.register("overlap", buildOverlap);
2139
+ r.register("crossed", buildCrossed);
2140
+ r.register("large", buildLarge);
2141
+ r.register("nest", buildNest);
2142
+ r.register("pit", buildPit);
2143
+ r.register("moria", buildMoria);
2144
+ r.register("room_of_chambers", buildRoomOfChambers);
2145
+ r.register("huge", buildHuge);
2146
+ /* build_template (gen-room.c L2972): the ROOM-TEMPLATE builder, not a vault
2147
+ * builder. All room templates are type 1 upstream. */
2148
+ r.register("template", (g, centre, rating) =>
2149
+ buildRoomTemplateType(g, centre, 1, rating, data.templates),
2150
+ );
2151
+ r.register("interesting", (g, centre) => buildVaultType(g, centre, "Interesting room", data.vaults));
2152
+ r.register("lesser_vault", (g, centre) => buildVaultType(g, centre, "Lesser vault", data.vaults));
2153
+ r.register("medium_vault", (g, centre) => buildVaultType(g, centre, "Medium vault", data.vaults));
2154
+ /* build_greater_vault / build_greater_new_vault (gen-room.c L3112, L3125) go
2155
+ * through help_greater_vault, NOT straight to build_vault_type. */
2156
+ r.register("greater_vault", (g, centre) => helpGreaterVault(g, centre, "Greater vault", data.vaults));
2157
+ r.register("lesser_new_vault", (g, centre) => buildVaultType(g, centre, "Lesser vault (new)", data.vaults));
2158
+ r.register("medium_new_vault", (g, centre) => buildVaultType(g, centre, "Medium vault (new)", data.vaults));
2159
+ r.register("greater_new_vault", (g, centre) =>
2160
+ helpGreaterVault(g, centre, "Greater vault (new)", data.vaults),
2161
+ );
2162
+ return r;
2163
+ }
2164
+
2165
+ /**
2166
+ * room_build: attempt to build a room of the given profile at a block, or (if
2167
+ * findsOwnSpace) let the builder find its own space. The builder is resolved
2168
+ * from the string-keyed registry, so modded builders dispatch identically.
2169
+ */
2170
+ export function roomBuild(
2171
+ g: Gen,
2172
+ by0: number,
2173
+ bx0: number,
2174
+ profile: RoomProfile,
2175
+ findsOwnSpace: boolean,
2176
+ registry: RoomRegistry,
2177
+ ): boolean {
2178
+ const dun = g.dun;
2179
+ const by1 = by0;
2180
+ const bx1 = bx0;
2181
+ let by2 = by0 + Math.trunc(profile.height / dun.blockHgt);
2182
+ let bx2 = bx0 + Math.trunc(profile.width / dun.blockWid);
2183
+
2184
+ if (g.c.depth < profile.level) return false;
2185
+ if (dun.pitNum >= dun.levelPitMax && profile.pit) return false;
2186
+
2187
+ if (profile.height % dun.blockHgt) by2++;
2188
+ if (profile.width % dun.blockWid) bx2++;
2189
+
2190
+ const builder = registry.get(profile.builder);
2191
+
2192
+ if (findsOwnSpace) {
2193
+ if (!builder(g, loc(g.c.width, g.c.height), profile.rating)) return false;
2194
+ } else {
2195
+ if (!checkForUnreservedBlocks(g, by1, bx1, by2, bx2)) return false;
2196
+ const centre = loc(
2197
+ Math.trunc(((bx1 + bx2 + 1) * dun.blockWid) / 2),
2198
+ Math.trunc(((by1 + by2 + 1) * dun.blockHgt) / 2),
2199
+ );
2200
+ if (dun.centN < dun.levelRoomMax) {
2201
+ dun.cent[dun.centN] = centre;
2202
+ dun.centN++;
2203
+ }
2204
+ if (!builder(g, centre, profile.rating)) {
2205
+ dun.centN--;
2206
+ return false;
2207
+ }
2208
+ reserveBlocks(g, by1, bx1, by2, bx2);
2209
+ }
2210
+
2211
+ if (profile.pit) dun.pitNum++;
2212
+ return true;
2213
+ }