@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.
- package/LICENSE.md +43 -0
- package/README.md +80 -0
- package/dist/agent/act.d.ts +22 -0
- package/dist/agent/act.d.ts.map +1 -0
- package/dist/agent/act.js +88 -0
- package/dist/agent/act.js.map +1 -0
- package/dist/agent/controller.d.ts +34 -0
- package/dist/agent/controller.d.ts.map +1 -0
- package/dist/agent/controller.js +90 -0
- package/dist/agent/controller.js.map +1 -0
- package/dist/agent/events.d.ts +27 -0
- package/dist/agent/events.d.ts.map +1 -0
- package/dist/agent/events.js +31 -0
- package/dist/agent/events.js.map +1 -0
- package/dist/agent/index.d.ts +17 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +15 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/perceive.d.ts +21 -0
- package/dist/agent/perceive.d.ts.map +1 -0
- package/dist/agent/perceive.js +386 -0
- package/dist/agent/perceive.js.map +1 -0
- package/dist/agent/types.d.ts +436 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +63 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/bitflag.d.ts +199 -0
- package/dist/bitflag.d.ts.map +1 -0
- package/dist/bitflag.js +478 -0
- package/dist/bitflag.js.map +1 -0
- package/dist/cmd.d.ts +164 -0
- package/dist/cmd.d.ts.map +1 -0
- package/dist/cmd.js +350 -0
- package/dist/cmd.js.map +1 -0
- package/dist/color.d.ts +104 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +240 -0
- package/dist/color.js.map +1 -0
- package/dist/combat/brand-slay.d.ts +119 -0
- package/dist/combat/brand-slay.d.ts.map +1 -0
- package/dist/combat/brand-slay.js +264 -0
- package/dist/combat/brand-slay.js.map +1 -0
- package/dist/combat/hit.d.ts +198 -0
- package/dist/combat/hit.d.ts.map +1 -0
- package/dist/combat/hit.js +310 -0
- package/dist/combat/hit.js.map +1 -0
- package/dist/combat/index.d.ts +15 -0
- package/dist/combat/index.d.ts.map +1 -0
- package/dist/combat/index.js +15 -0
- package/dist/combat/index.js.map +1 -0
- package/dist/combat/melee.d.ts +261 -0
- package/dist/combat/melee.d.ts.map +1 -0
- package/dist/combat/melee.js +402 -0
- package/dist/combat/melee.js.map +1 -0
- package/dist/combat/mon-melee.d.ts +233 -0
- package/dist/combat/mon-melee.d.ts.map +1 -0
- package/dist/combat/mon-melee.js +883 -0
- package/dist/combat/mon-melee.js.map +1 -0
- package/dist/combat/ranged.d.ts +89 -0
- package/dist/combat/ranged.d.ts.map +1 -0
- package/dist/combat/ranged.js +253 -0
- package/dist/combat/ranged.js.map +1 -0
- package/dist/constants.d.ts +134 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +171 -0
- package/dist/constants.js.map +1 -0
- package/dist/dice.d.ts +91 -0
- package/dist/dice.d.ts.map +1 -0
- package/dist/dice.js +424 -0
- package/dist/dice.js.map +1 -0
- package/dist/effects/effect-choice.d.ts +15 -0
- package/dist/effects/effect-choice.d.ts.map +1 -0
- package/dist/effects/effect-choice.js +18 -0
- package/dist/effects/effect-choice.js.map +1 -0
- package/dist/effects/effect-info.d.ts +124 -0
- package/dist/effects/effect-info.d.ts.map +1 -0
- package/dist/effects/effect-info.js +706 -0
- package/dist/effects/effect-info.js.map +1 -0
- package/dist/effects/effect.d.ts +165 -0
- package/dist/effects/effect.d.ts.map +1 -0
- package/dist/effects/effect.js +452 -0
- package/dist/effects/effect.js.map +1 -0
- package/dist/effects/handlers.d.ts +70 -0
- package/dist/effects/handlers.d.ts.map +1 -0
- package/dist/effects/handlers.js +394 -0
- package/dist/effects/handlers.js.map +1 -0
- package/dist/effects/interpreter.d.ts +291 -0
- package/dist/effects/interpreter.d.ts.map +1 -0
- package/dist/effects/interpreter.js +325 -0
- package/dist/effects/interpreter.js.map +1 -0
- package/dist/events.d.ts +188 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +138 -0
- package/dist/events.js.map +1 -0
- package/dist/expression.d.ts +83 -0
- package/dist/expression.d.ts.map +1 -0
- package/dist/expression.js +333 -0
- package/dist/expression.js.map +1 -0
- package/dist/game/cave-cmd.d.ts +195 -0
- package/dist/game/cave-cmd.d.ts.map +1 -0
- package/dist/game/cave-cmd.js +968 -0
- package/dist/game/cave-cmd.js.map +1 -0
- package/dist/game/char-sheet.d.ts +189 -0
- package/dist/game/char-sheet.d.ts.map +1 -0
- package/dist/game/char-sheet.js +381 -0
- package/dist/game/char-sheet.js.map +1 -0
- package/dist/game/chest.d.ts +94 -0
- package/dist/game/chest.d.ts.map +1 -0
- package/dist/game/chest.js +267 -0
- package/dist/game/chest.js.map +1 -0
- package/dist/game/context.d.ts +970 -0
- package/dist/game/context.d.ts.map +1 -0
- package/dist/game/context.js +353 -0
- package/dist/game/context.js.map +1 -0
- package/dist/game/curse-tick.d.ts +35 -0
- package/dist/game/curse-tick.d.ts.map +1 -0
- package/dist/game/curse-tick.js +100 -0
- package/dist/game/curse-tick.js.map +1 -0
- package/dist/game/describe.d.ts +20 -0
- package/dist/game/describe.d.ts.map +1 -0
- package/dist/game/describe.js +45 -0
- package/dist/game/describe.js.map +1 -0
- package/dist/game/display.d.ts +196 -0
- package/dist/game/display.d.ts.map +1 -0
- package/dist/game/display.js +684 -0
- package/dist/game/display.js.map +1 -0
- package/dist/game/dump-level.d.ts +37 -0
- package/dist/game/dump-level.d.ts.map +1 -0
- package/dist/game/dump-level.js +110 -0
- package/dist/game/dump-level.js.map +1 -0
- package/dist/game/effect-attack.d.ts +36 -0
- package/dist/game/effect-attack.d.ts.map +1 -0
- package/dist/game/effect-attack.js +694 -0
- package/dist/game/effect-attack.js.map +1 -0
- package/dist/game/effect-detect.d.ts +34 -0
- package/dist/game/effect-detect.d.ts.map +1 -0
- package/dist/game/effect-detect.js +456 -0
- package/dist/game/effect-detect.js.map +1 -0
- package/dist/game/effect-env.d.ts +77 -0
- package/dist/game/effect-env.d.ts.map +1 -0
- package/dist/game/effect-env.js +166 -0
- package/dist/game/effect-env.js.map +1 -0
- package/dist/game/effect-game-env.d.ts +76 -0
- package/dist/game/effect-game-env.d.ts.map +1 -0
- package/dist/game/effect-game-env.js +23 -0
- package/dist/game/effect-game-env.js.map +1 -0
- package/dist/game/effect-general.d.ts +98 -0
- package/dist/game/effect-general.d.ts.map +1 -0
- package/dist/game/effect-general.js +914 -0
- package/dist/game/effect-general.js.map +1 -0
- package/dist/game/effect-item.d.ts +124 -0
- package/dist/game/effect-item.d.ts.map +1 -0
- package/dist/game/effect-item.js +789 -0
- package/dist/game/effect-item.js.map +1 -0
- package/dist/game/effect-melee.d.ts +43 -0
- package/dist/game/effect-melee.d.ts.map +1 -0
- package/dist/game/effect-melee.js +477 -0
- package/dist/game/effect-melee.js.map +1 -0
- package/dist/game/effect-mon-origin.d.ts +67 -0
- package/dist/game/effect-mon-origin.d.ts.map +1 -0
- package/dist/game/effect-mon-origin.js +164 -0
- package/dist/game/effect-mon-origin.js.map +1 -0
- package/dist/game/effect-monster.d.ts +29 -0
- package/dist/game/effect-monster.d.ts.map +1 -0
- package/dist/game/effect-monster.js +281 -0
- package/dist/game/effect-monster.js.map +1 -0
- package/dist/game/effect-summon.d.ts +37 -0
- package/dist/game/effect-summon.d.ts.map +1 -0
- package/dist/game/effect-summon.js +113 -0
- package/dist/game/effect-summon.js.map +1 -0
- package/dist/game/effect-teleport.d.ts +130 -0
- package/dist/game/effect-teleport.d.ts.map +1 -0
- package/dist/game/effect-teleport.js +529 -0
- package/dist/game/effect-teleport.js.map +1 -0
- package/dist/game/effect-terrain.d.ts +91 -0
- package/dist/game/effect-terrain.d.ts.map +1 -0
- package/dist/game/effect-terrain.js +812 -0
- package/dist/game/effect-terrain.js.map +1 -0
- package/dist/game/energy.d.ts +45 -0
- package/dist/game/energy.d.ts.map +1 -0
- package/dist/game/energy.js +51 -0
- package/dist/game/energy.js.map +1 -0
- package/dist/game/equip-cmp.d.ts +138 -0
- package/dist/game/equip-cmp.d.ts.map +1 -0
- package/dist/game/equip-cmp.js +363 -0
- package/dist/game/equip-cmp.js.map +1 -0
- package/dist/game/floor.d.ts +182 -0
- package/dist/game/floor.d.ts.map +1 -0
- package/dist/game/floor.js +435 -0
- package/dist/game/floor.js.map +1 -0
- package/dist/game/gear.d.ts +408 -0
- package/dist/game/gear.d.ts.map +1 -0
- package/dist/game/gear.js +1037 -0
- package/dist/game/gear.js.map +1 -0
- package/dist/game/harness.d.ts +61 -0
- package/dist/game/harness.d.ts.map +1 -0
- package/dist/game/harness.js +198 -0
- package/dist/game/harness.js.map +1 -0
- package/dist/game/history.d.ts +49 -0
- package/dist/game/history.d.ts.map +1 -0
- package/dist/game/history.js +55 -0
- package/dist/game/history.js.map +1 -0
- package/dist/game/ignore-cmd.d.ts +42 -0
- package/dist/game/ignore-cmd.d.ts.map +1 -0
- package/dist/game/ignore-cmd.js +59 -0
- package/dist/game/ignore-cmd.js.map +1 -0
- package/dist/game/inscription-confirm.d.ts +80 -0
- package/dist/game/inscription-confirm.d.ts.map +1 -0
- package/dist/game/inscription-confirm.js +95 -0
- package/dist/game/inscription-confirm.js.map +1 -0
- package/dist/game/known.d.ts +297 -0
- package/dist/game/known.d.ts.map +1 -0
- package/dist/game/known.js +849 -0
- package/dist/game/known.js.map +1 -0
- package/dist/game/loop.d.ts +139 -0
- package/dist/game/loop.d.ts.map +1 -0
- package/dist/game/loop.js +631 -0
- package/dist/game/loop.js.map +1 -0
- package/dist/game/lore-color.d.ts +25 -0
- package/dist/game/lore-color.d.ts.map +1 -0
- package/dist/game/lore-color.js +95 -0
- package/dist/game/lore-color.js.map +1 -0
- package/dist/game/mon-cast.d.ts +150 -0
- package/dist/game/mon-cast.d.ts.map +1 -0
- package/dist/game/mon-cast.js +301 -0
- package/dist/game/mon-cast.js.map +1 -0
- package/dist/game/mon-cmd.d.ts +51 -0
- package/dist/game/mon-cmd.d.ts.map +1 -0
- package/dist/game/mon-cmd.js +670 -0
- package/dist/game/mon-cmd.js.map +1 -0
- package/dist/game/mon-death.d.ts +143 -0
- package/dist/game/mon-death.d.ts.map +1 -0
- package/dist/game/mon-death.js +328 -0
- package/dist/game/mon-death.js.map +1 -0
- package/dist/game/mon-group.d.ts +81 -0
- package/dist/game/mon-group.d.ts.map +1 -0
- package/dist/game/mon-group.js +323 -0
- package/dist/game/mon-group.js.map +1 -0
- package/dist/game/mon-list.d.ts +85 -0
- package/dist/game/mon-list.d.ts.map +1 -0
- package/dist/game/mon-list.js +154 -0
- package/dist/game/mon-list.js.map +1 -0
- package/dist/game/mon-message.d.ts +100 -0
- package/dist/game/mon-message.d.ts.map +1 -0
- package/dist/game/mon-message.js +336 -0
- package/dist/game/mon-message.js.map +1 -0
- package/dist/game/mon-place.d.ts +226 -0
- package/dist/game/mon-place.d.ts.map +1 -0
- package/dist/game/mon-place.js +642 -0
- package/dist/game/mon-place.js.map +1 -0
- package/dist/game/mon-ranged.d.ts +87 -0
- package/dist/game/mon-ranged.d.ts.map +1 -0
- package/dist/game/mon-ranged.js +353 -0
- package/dist/game/mon-ranged.js.map +1 -0
- package/dist/game/mon-shape.d.ts +43 -0
- package/dist/game/mon-shape.d.ts.map +1 -0
- package/dist/game/mon-shape.js +115 -0
- package/dist/game/mon-shape.js.map +1 -0
- package/dist/game/mon-side.d.ts +63 -0
- package/dist/game/mon-side.d.ts.map +1 -0
- package/dist/game/mon-side.js +403 -0
- package/dist/game/mon-side.js.map +1 -0
- package/dist/game/monster-turn.d.ts +195 -0
- package/dist/game/monster-turn.d.ts.map +1 -0
- package/dist/game/monster-turn.js +1560 -0
- package/dist/game/monster-turn.js.map +1 -0
- package/dist/game/obj-cmd.d.ts +453 -0
- package/dist/game/obj-cmd.d.ts.map +1 -0
- package/dist/game/obj-cmd.js +1530 -0
- package/dist/game/obj-cmd.js.map +1 -0
- package/dist/game/obj-list.d.ts +92 -0
- package/dist/game/obj-list.d.ts.map +1 -0
- package/dist/game/obj-list.js +251 -0
- package/dist/game/obj-list.js.map +1 -0
- package/dist/game/object-inspect.d.ts +37 -0
- package/dist/game/object-inspect.d.ts.map +1 -0
- package/dist/game/object-inspect.js +106 -0
- package/dist/game/object-inspect.js.map +1 -0
- package/dist/game/pickup.d.ts +126 -0
- package/dist/game/pickup.d.ts.map +1 -0
- package/dist/game/pickup.js +367 -0
- package/dist/game/pickup.js.map +1 -0
- package/dist/game/player-path.d.ts +133 -0
- package/dist/game/player-path.d.ts.map +1 -0
- package/dist/game/player-path.js +1268 -0
- package/dist/game/player-path.js.map +1 -0
- package/dist/game/player-side.d.ts +59 -0
- package/dist/game/player-side.d.ts.map +1 -0
- package/dist/game/player-side.js +506 -0
- package/dist/game/player-side.js.map +1 -0
- package/dist/game/player-turn.d.ts +161 -0
- package/dist/game/player-turn.d.ts.map +1 -0
- package/dist/game/player-turn.js +739 -0
- package/dist/game/player-turn.js.map +1 -0
- package/dist/game/project-cast.d.ts +268 -0
- package/dist/game/project-cast.d.ts.map +1 -0
- package/dist/game/project-cast.js +496 -0
- package/dist/game/project-cast.js.map +1 -0
- package/dist/game/project-feat.d.ts +47 -0
- package/dist/game/project-feat.d.ts.map +1 -0
- package/dist/game/project-feat.js +350 -0
- package/dist/game/project-feat.js.map +1 -0
- package/dist/game/project-monster.d.ts +106 -0
- package/dist/game/project-monster.d.ts.map +1 -0
- package/dist/game/project-monster.js +272 -0
- package/dist/game/project-monster.js.map +1 -0
- package/dist/game/project-obj.d.ts +60 -0
- package/dist/game/project-obj.d.ts.map +1 -0
- package/dist/game/project-obj.js +245 -0
- package/dist/game/project-obj.js.map +1 -0
- package/dist/game/project-player.d.ts +120 -0
- package/dist/game/project-player.d.ts.map +1 -0
- package/dist/game/project-player.js +108 -0
- package/dist/game/project-player.js.map +1 -0
- package/dist/game/quest.d.ts +101 -0
- package/dist/game/quest.d.ts.map +1 -0
- package/dist/game/quest.js +192 -0
- package/dist/game/quest.js.map +1 -0
- package/dist/game/ranged-cmd.d.ts +32 -0
- package/dist/game/ranged-cmd.d.ts.map +1 -0
- package/dist/game/ranged-cmd.js +372 -0
- package/dist/game/ranged-cmd.js.map +1 -0
- package/dist/game/scheduler.d.ts +47 -0
- package/dist/game/scheduler.d.ts.map +1 -0
- package/dist/game/scheduler.js +141 -0
- package/dist/game/scheduler.js.map +1 -0
- package/dist/game/spell-cmd.d.ts +104 -0
- package/dist/game/spell-cmd.d.ts.map +1 -0
- package/dist/game/spell-cmd.js +320 -0
- package/dist/game/spell-cmd.js.map +1 -0
- package/dist/game/spoil.d.ts +28 -0
- package/dist/game/spoil.d.ts.map +1 -0
- package/dist/game/spoil.js +435 -0
- package/dist/game/spoil.js.map +1 -0
- package/dist/game/steal.d.ts +35 -0
- package/dist/game/steal.d.ts.map +1 -0
- package/dist/game/steal.js +145 -0
- package/dist/game/steal.js.map +1 -0
- package/dist/game/take-hit-hooks.d.ts +52 -0
- package/dist/game/take-hit-hooks.d.ts.map +1 -0
- package/dist/game/take-hit-hooks.js +127 -0
- package/dist/game/take-hit-hooks.js.map +1 -0
- package/dist/game/target-loop.d.ts +119 -0
- package/dist/game/target-loop.d.ts.map +1 -0
- package/dist/game/target-loop.js +408 -0
- package/dist/game/target-loop.js.map +1 -0
- package/dist/game/target.d.ts +133 -0
- package/dist/game/target.d.ts.map +1 -0
- package/dist/game/target.js +353 -0
- package/dist/game/target.js.map +1 -0
- package/dist/game/thrust.d.ts +37 -0
- package/dist/game/thrust.d.ts.map +1 -0
- package/dist/game/thrust.js +155 -0
- package/dist/game/thrust.js.map +1 -0
- package/dist/game/trap.d.ts +218 -0
- package/dist/game/trap.d.ts.map +1 -0
- package/dist/game/trap.js +618 -0
- package/dist/game/trap.js.map +1 -0
- package/dist/game/ui-entry.d.ts +282 -0
- package/dist/game/ui-entry.d.ts.map +1 -0
- package/dist/game/ui-entry.js +1838 -0
- package/dist/game/ui-entry.js.map +1 -0
- package/dist/game/wizard.d.ts +654 -0
- package/dist/game/wizard.d.ts.map +1 -0
- package/dist/game/wizard.js +1323 -0
- package/dist/game/wizard.js.map +1 -0
- package/dist/game/world.d.ts +183 -0
- package/dist/game/world.d.ts.map +1 -0
- package/dist/game/world.js +685 -0
- package/dist/game/world.js.map +1 -0
- package/dist/gen/cave.d.ts +247 -0
- package/dist/gen/cave.d.ts.map +1 -0
- package/dist/gen/cave.js +2406 -0
- package/dist/gen/cave.js.map +1 -0
- package/dist/gen/gen-monster.d.ts +151 -0
- package/dist/gen/gen-monster.d.ts.map +1 -0
- package/dist/gen/gen-monster.js +473 -0
- package/dist/gen/gen-monster.js.map +1 -0
- package/dist/gen/generate.d.ts +240 -0
- package/dist/gen/generate.d.ts.map +1 -0
- package/dist/gen/generate.js +358 -0
- package/dist/gen/generate.js.map +1 -0
- package/dist/gen/room.d.ts +160 -0
- package/dist/gen/room.d.ts.map +1 -0
- package/dist/gen/room.js +1910 -0
- package/dist/gen/room.js.map +1 -0
- package/dist/gen/util.d.ts +466 -0
- package/dist/gen/util.d.ts.map +1 -0
- package/dist/gen/util.js +1553 -0
- package/dist/gen/util.js.map +1 -0
- package/dist/generated/dun-profiles.d.ts +44 -0
- package/dist/generated/dun-profiles.d.ts.map +1 -0
- package/dist/generated/dun-profiles.js +28 -0
- package/dist/generated/dun-profiles.js.map +1 -0
- package/dist/generated/effects.d.ts +1021 -0
- package/dist/generated/effects.d.ts.map +1 -0
- package/dist/generated/effects.js +239 -0
- package/dist/generated/effects.js.map +1 -0
- package/dist/generated/elements.d.ts +83 -0
- package/dist/generated/elements.d.ts.map +1 -0
- package/dist/generated/elements.js +60 -0
- package/dist/generated/elements.js.map +1 -0
- package/dist/generated/equip-slots.d.ts +104 -0
- package/dist/generated/equip-slots.d.ts.map +1 -0
- package/dist/generated/equip-slots.js +34 -0
- package/dist/generated/equip-slots.js.map +1 -0
- package/dist/generated/history-types.d.ts +52 -0
- package/dist/generated/history-types.d.ts.map +1 -0
- package/dist/generated/history-types.js +32 -0
- package/dist/generated/history-types.js.map +1 -0
- package/dist/generated/ignore-types.d.ts +116 -0
- package/dist/generated/ignore-types.d.ts.map +1 -0
- package/dist/generated/ignore-types.js +64 -0
- package/dist/generated/ignore-types.js.map +1 -0
- package/dist/generated/index.d.ts +32 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +33 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/generated/kind-flags.d.ts +72 -0
- package/dist/generated/kind-flags.d.ts.map +1 -0
- package/dist/generated/kind-flags.js +42 -0
- package/dist/generated/kind-flags.js.map +1 -0
- package/dist/generated/message.d.ts +624 -0
- package/dist/generated/message.d.ts.map +1 -0
- package/dist/generated/message.js +318 -0
- package/dist/generated/message.js.map +1 -0
- package/dist/generated/mon-message.d.ts +386 -0
- package/dist/generated/mon-message.d.ts.map +1 -0
- package/dist/generated/mon-message.js +136 -0
- package/dist/generated/mon-message.js.map +1 -0
- package/dist/generated/mon-race-flags.d.ts +433 -0
- package/dist/generated/mon-race-flags.d.ts.map +1 -0
- package/dist/generated/mon-race-flags.js +180 -0
- package/dist/generated/mon-race-flags.js.map +1 -0
- package/dist/generated/mon-spells.d.ts +380 -0
- package/dist/generated/mon-spells.d.ts.map +1 -0
- package/dist/generated/mon-spells.js +196 -0
- package/dist/generated/mon-spells.js.map +1 -0
- package/dist/generated/mon-temp-flags.d.ts +52 -0
- package/dist/generated/mon-temp-flags.d.ts.map +1 -0
- package/dist/generated/mon-temp-flags.js +32 -0
- package/dist/generated/mon-temp-flags.js.map +1 -0
- package/dist/generated/mon-timed.d.ts +118 -0
- package/dist/generated/mon-timed.d.ts.map +1 -0
- package/dist/generated/mon-timed.js +32 -0
- package/dist/generated/mon-timed.js.map +1 -0
- package/dist/generated/object-flags.d.ts +169 -0
- package/dist/generated/object-flags.d.ts.map +1 -0
- package/dist/generated/object-flags.js +93 -0
- package/dist/generated/object-flags.js.map +1 -0
- package/dist/generated/object-modifiers.d.ts +50 -0
- package/dist/generated/object-modifiers.d.ts.map +1 -0
- package/dist/generated/object-modifiers.js +41 -0
- package/dist/generated/object-modifiers.js.map +1 -0
- package/dist/generated/options.d.ts +284 -0
- package/dist/generated/options.d.ts.map +1 -0
- package/dist/generated/options.js +102 -0
- package/dist/generated/options.js.map +1 -0
- package/dist/generated/origins.d.ts +138 -0
- package/dist/generated/origins.d.ts.map +1 -0
- package/dist/generated/origins.js +62 -0
- package/dist/generated/origins.js.map +1 -0
- package/dist/generated/parser-errors.d.ts +264 -0
- package/dist/generated/parser-errors.d.ts.map +1 -0
- package/dist/generated/parser-errors.js +138 -0
- package/dist/generated/parser-errors.js.map +1 -0
- package/dist/generated/player-flags.d.ts +62 -0
- package/dist/generated/player-flags.d.ts.map +1 -0
- package/dist/generated/player-flags.js +46 -0
- package/dist/generated/player-flags.js.map +1 -0
- package/dist/generated/player-timed.d.ts +273 -0
- package/dist/generated/player-timed.d.ts.map +1 -0
- package/dist/generated/player-timed.js +116 -0
- package/dist/generated/player-timed.js.map +1 -0
- package/dist/generated/projections.d.ts +130 -0
- package/dist/generated/projections.d.ts.map +1 -0
- package/dist/generated/projections.js +101 -0
- package/dist/generated/projections.js.map +1 -0
- package/dist/generated/randart-properties.d.ts +388 -0
- package/dist/generated/randart-properties.d.ts.map +1 -0
- package/dist/generated/randart-properties.js +200 -0
- package/dist/generated/randart-properties.js.map +1 -0
- package/dist/generated/room-flags.d.ts +21 -0
- package/dist/generated/room-flags.d.ts.map +1 -0
- package/dist/generated/room-flags.js +19 -0
- package/dist/generated/room-flags.js.map +1 -0
- package/dist/generated/rooms.d.ts +122 -0
- package/dist/generated/rooms.d.ts.map +1 -0
- package/dist/generated/rooms.js +48 -0
- package/dist/generated/rooms.js.map +1 -0
- package/dist/generated/square-flags.d.ts +96 -0
- package/dist/generated/square-flags.d.ts.map +1 -0
- package/dist/generated/square-flags.js +54 -0
- package/dist/generated/square-flags.js.map +1 -0
- package/dist/generated/stats.d.ts +23 -0
- package/dist/generated/stats.d.ts.map +1 -0
- package/dist/generated/stats.js +20 -0
- package/dist/generated/stats.js.map +1 -0
- package/dist/generated/terrain-flags.d.ts +136 -0
- package/dist/generated/terrain-flags.d.ts.map +1 -0
- package/dist/generated/terrain-flags.js +74 -0
- package/dist/generated/terrain-flags.js.map +1 -0
- package/dist/generated/terrain.d.ts +83 -0
- package/dist/generated/terrain.d.ts.map +1 -0
- package/dist/generated/terrain.js +60 -0
- package/dist/generated/terrain.js.map +1 -0
- package/dist/generated/trap-flags.d.ts +68 -0
- package/dist/generated/trap-flags.d.ts.map +1 -0
- package/dist/generated/trap-flags.js +40 -0
- package/dist/generated/trap-flags.js.map +1 -0
- package/dist/generated/tvals.d.ts +152 -0
- package/dist/generated/tvals.d.ts.map +1 -0
- package/dist/generated/tvals.js +82 -0
- package/dist/generated/tvals.js.map +1 -0
- package/dist/generated/ui-entry-renderers.d.ts +62 -0
- package/dist/generated/ui-entry-renderers.d.ts.map +1 -0
- package/dist/generated/ui-entry-renderers.js +22 -0
- package/dist/generated/ui-entry-renderers.js.map +1 -0
- package/dist/guard.d.ts +43 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +65 -0
- package/dist/guard.js.map +1 -0
- package/dist/host/args.d.ts +129 -0
- package/dist/host/args.d.ts.map +1 -0
- package/dist/host/args.js +251 -0
- package/dist/host/args.js.map +1 -0
- package/dist/host/bridge.d.ts +61 -0
- package/dist/host/bridge.d.ts.map +1 -0
- package/dist/host/bridge.js +176 -0
- package/dist/host/bridge.js.map +1 -0
- package/dist/host/index.d.ts +18 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +18 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/io.d.ts +169 -0
- package/dist/host/io.d.ts.map +1 -0
- package/dist/host/io.js +137 -0
- package/dist/host/io.js.map +1 -0
- package/dist/host/memory.d.ts +56 -0
- package/dist/host/memory.d.ts.map +1 -0
- package/dist/host/memory.js +105 -0
- package/dist/host/memory.js.map +1 -0
- package/dist/host/raw.d.ts +114 -0
- package/dist/host/raw.d.ts.map +1 -0
- package/dist/host/raw.js +107 -0
- package/dist/host/raw.js.map +1 -0
- package/dist/index.d.ts +180 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +222 -0
- package/dist/index.js.map +1 -0
- package/dist/loc.d.ts +63 -0
- package/dist/loc.d.ts.map +1 -0
- package/dist/loc.js +128 -0
- package/dist/loc.js.map +1 -0
- package/dist/mod/hooks.d.ts +204 -0
- package/dist/mod/hooks.d.ts.map +1 -0
- package/dist/mod/hooks.js +161 -0
- package/dist/mod/hooks.js.map +1 -0
- package/dist/mod/ids.d.ts +160 -0
- package/dist/mod/ids.d.ts.map +1 -0
- package/dist/mod/ids.js +343 -0
- package/dist/mod/ids.js.map +1 -0
- package/dist/mod/registry-host.d.ts +156 -0
- package/dist/mod/registry-host.d.ts.map +1 -0
- package/dist/mod/registry-host.js +142 -0
- package/dist/mod/registry-host.js.map +1 -0
- package/dist/mod/save-blocks.d.ts +201 -0
- package/dist/mod/save-blocks.d.ts.map +1 -0
- package/dist/mod/save-blocks.js +640 -0
- package/dist/mod/save-blocks.js.map +1 -0
- package/dist/mod/vocabulary.d.ts +104 -0
- package/dist/mod/vocabulary.d.ts.map +1 -0
- package/dist/mod/vocabulary.js +0 -0
- package/dist/mod/vocabulary.js.map +1 -0
- package/dist/mon/bind.d.ts +266 -0
- package/dist/mon/bind.d.ts.map +1 -0
- package/dist/mon/bind.js +610 -0
- package/dist/mon/bind.js.map +1 -0
- package/dist/mon/desc.d.ts +72 -0
- package/dist/mon/desc.d.ts.map +1 -0
- package/dist/mon/desc.js +237 -0
- package/dist/mon/desc.js.map +1 -0
- package/dist/mon/knowledge-groups.d.ts +61 -0
- package/dist/mon/knowledge-groups.d.ts.map +1 -0
- package/dist/mon/knowledge-groups.js +121 -0
- package/dist/mon/knowledge-groups.js.map +1 -0
- package/dist/mon/lore-describe.d.ts +216 -0
- package/dist/mon/lore-describe.d.ts.map +1 -0
- package/dist/mon/lore-describe.js +1105 -0
- package/dist/mon/lore-describe.js.map +1 -0
- package/dist/mon/lore.d.ts +117 -0
- package/dist/mon/lore.d.ts.map +1 -0
- package/dist/mon/lore.js +221 -0
- package/dist/mon/lore.js.map +1 -0
- package/dist/mon/make.d.ts +147 -0
- package/dist/mon/make.d.ts.map +1 -0
- package/dist/mon/make.js +353 -0
- package/dist/mon/make.js.map +1 -0
- package/dist/mon/monster.d.ts +94 -0
- package/dist/mon/monster.d.ts.map +1 -0
- package/dist/mon/monster.js +90 -0
- package/dist/mon/monster.js.map +1 -0
- package/dist/mon/predicate.d.ts +87 -0
- package/dist/mon/predicate.d.ts.map +1 -0
- package/dist/mon/predicate.js +190 -0
- package/dist/mon/predicate.js.map +1 -0
- package/dist/mon/project-mon.d.ts +129 -0
- package/dist/mon/project-mon.d.ts.map +1 -0
- package/dist/mon/project-mon.js +652 -0
- package/dist/mon/project-mon.js.map +1 -0
- package/dist/mon/spell.d.ts +155 -0
- package/dist/mon/spell.d.ts.map +1 -0
- package/dist/mon/spell.js +355 -0
- package/dist/mon/spell.js.map +1 -0
- package/dist/mon/steal.d.ts +112 -0
- package/dist/mon/steal.d.ts.map +1 -0
- package/dist/mon/steal.js +163 -0
- package/dist/mon/steal.js.map +1 -0
- package/dist/mon/summon.d.ts +62 -0
- package/dist/mon/summon.d.ts.map +1 -0
- package/dist/mon/summon.js +111 -0
- package/dist/mon/summon.js.map +1 -0
- package/dist/mon/take-hit.d.ts +75 -0
- package/dist/mon/take-hit.d.ts.map +1 -0
- package/dist/mon/take-hit.js +122 -0
- package/dist/mon/take-hit.js.map +1 -0
- package/dist/mon/timed.d.ts +74 -0
- package/dist/mon/timed.d.ts.map +1 -0
- package/dist/mon/timed.js +219 -0
- package/dist/mon/timed.js.map +1 -0
- package/dist/mon/types.d.ts +252 -0
- package/dist/mon/types.d.ts.map +1 -0
- package/dist/mon/types.js +46 -0
- package/dist/mon/types.js.map +1 -0
- package/dist/msg.d.ts +71 -0
- package/dist/msg.d.ts.map +1 -0
- package/dist/msg.js +126 -0
- package/dist/msg.js.map +1 -0
- package/dist/obj/artifact-fake.d.ts +39 -0
- package/dist/obj/artifact-fake.d.ts.map +1 -0
- package/dist/obj/artifact-fake.js +52 -0
- package/dist/obj/artifact-fake.js.map +1 -0
- package/dist/obj/artifact-known.d.ts +50 -0
- package/dist/obj/artifact-known.d.ts.map +1 -0
- package/dist/obj/artifact-known.js +55 -0
- package/dist/obj/artifact-known.js.map +1 -0
- package/dist/obj/bind.d.ts +219 -0
- package/dist/obj/bind.d.ts.map +1 -0
- package/dist/obj/bind.js +1239 -0
- package/dist/obj/bind.js.map +1 -0
- package/dist/obj/chest.d.ts +91 -0
- package/dist/obj/chest.d.ts.map +1 -0
- package/dist/obj/chest.js +220 -0
- package/dist/obj/chest.js.map +1 -0
- package/dist/obj/desc.d.ts +79 -0
- package/dist/obj/desc.d.ts.map +1 -0
- package/dist/obj/desc.js +602 -0
- package/dist/obj/desc.js.map +1 -0
- package/dist/obj/effects-info.d.ts +78 -0
- package/dist/obj/effects-info.d.ts.map +1 -0
- package/dist/obj/effects-info.js +240 -0
- package/dist/obj/effects-info.js.map +1 -0
- package/dist/obj/flavor.d.ts +68 -0
- package/dist/obj/flavor.d.ts.map +1 -0
- package/dist/obj/flavor.js +201 -0
- package/dist/obj/flavor.js.map +1 -0
- package/dist/obj/ignore.d.ts +143 -0
- package/dist/obj/ignore.d.ts.map +1 -0
- package/dist/obj/ignore.js +345 -0
- package/dist/obj/ignore.js.map +1 -0
- package/dist/obj/knowledge.d.ts +520 -0
- package/dist/obj/knowledge.d.ts.map +1 -0
- package/dist/obj/knowledge.js +1364 -0
- package/dist/obj/knowledge.js.map +1 -0
- package/dist/obj/known-object.d.ts +293 -0
- package/dist/obj/known-object.d.ts.map +1 -0
- package/dist/obj/known-object.js +532 -0
- package/dist/obj/known-object.js.map +1 -0
- package/dist/obj/make.d.ts +292 -0
- package/dist/obj/make.d.ts.map +1 -0
- package/dist/obj/make.js +1055 -0
- package/dist/obj/make.js.map +1 -0
- package/dist/obj/object-info.d.ts +188 -0
- package/dist/obj/object-info.d.ts.map +1 -0
- package/dist/obj/object-info.js +1407 -0
- package/dist/obj/object-info.js.map +1 -0
- package/dist/obj/object.d.ts +335 -0
- package/dist/obj/object.d.ts.map +1 -0
- package/dist/obj/object.js +1051 -0
- package/dist/obj/object.js.map +1 -0
- package/dist/obj/power.d.ts +65 -0
- package/dist/obj/power.d.ts.map +1 -0
- package/dist/obj/power.js +580 -0
- package/dist/obj/power.js.map +1 -0
- package/dist/obj/randart-build.d.ts +223 -0
- package/dist/obj/randart-build.d.ts.map +1 -0
- package/dist/obj/randart-build.js +1444 -0
- package/dist/obj/randart-build.js.map +1 -0
- package/dist/obj/randart-data.d.ts +179 -0
- package/dist/obj/randart-data.d.ts.map +1 -0
- package/dist/obj/randart-data.js +1153 -0
- package/dist/obj/randart-data.js.map +1 -0
- package/dist/obj/randart.d.ts +128 -0
- package/dist/obj/randart.d.ts.map +1 -0
- package/dist/obj/randart.js +458 -0
- package/dist/obj/randart.js.map +1 -0
- package/dist/obj/randname.d.ts +33 -0
- package/dist/obj/randname.d.ts.map +1 -0
- package/dist/obj/randname.js +116 -0
- package/dist/obj/randname.js.map +1 -0
- package/dist/obj/recharge.d.ts +28 -0
- package/dist/obj/recharge.d.ts.map +1 -0
- package/dist/obj/recharge.js +52 -0
- package/dist/obj/recharge.js.map +1 -0
- package/dist/obj/types.d.ts +584 -0
- package/dist/obj/types.d.ts.map +1 -0
- package/dist/obj/types.js +104 -0
- package/dist/obj/types.js.map +1 -0
- package/dist/obj/value.d.ts +64 -0
- package/dist/obj/value.d.ts.map +1 -0
- package/dist/obj/value.js +176 -0
- package/dist/obj/value.js.map +1 -0
- package/dist/player/abilities.d.ts +57 -0
- package/dist/player/abilities.d.ts.map +1 -0
- package/dist/player/abilities.js +118 -0
- package/dist/player/abilities.js.map +1 -0
- package/dist/player/best-digger.d.ts +42 -0
- package/dist/player/best-digger.d.ts.map +1 -0
- package/dist/player/best-digger.js +89 -0
- package/dist/player/best-digger.js.map +1 -0
- package/dist/player/bind.d.ts +270 -0
- package/dist/player/bind.d.ts.map +1 -0
- package/dist/player/bind.js +698 -0
- package/dist/player/bind.js.map +1 -0
- package/dist/player/birth.d.ts +258 -0
- package/dist/player/birth.d.ts.map +1 -0
- package/dist/player/birth.js +639 -0
- package/dist/player/birth.js.map +1 -0
- package/dist/player/calcs.d.ts +403 -0
- package/dist/player/calcs.d.ts.map +1 -0
- package/dist/player/calcs.js +1189 -0
- package/dist/player/calcs.js.map +1 -0
- package/dist/player/combat-regen.d.ts +14 -0
- package/dist/player/combat-regen.d.ts.map +1 -0
- package/dist/player/combat-regen.js +29 -0
- package/dist/player/combat-regen.js.map +1 -0
- package/dist/player/exp.d.ts +96 -0
- package/dist/player/exp.d.ts.map +1 -0
- package/dist/player/exp.js +229 -0
- package/dist/player/exp.js.map +1 -0
- package/dist/player/history.d.ts +91 -0
- package/dist/player/history.d.ts.map +1 -0
- package/dist/player/history.js +145 -0
- package/dist/player/history.js.map +1 -0
- package/dist/player/options.d.ts +123 -0
- package/dist/player/options.d.ts.map +1 -0
- package/dist/player/options.js +199 -0
- package/dist/player/options.js.map +1 -0
- package/dist/player/player.d.ts +242 -0
- package/dist/player/player.d.ts.map +1 -0
- package/dist/player/player.js +119 -0
- package/dist/player/player.js.map +1 -0
- package/dist/player/shape-lore.d.ts +56 -0
- package/dist/player/shape-lore.d.ts.map +1 -0
- package/dist/player/shape-lore.js +221 -0
- package/dist/player/shape-lore.js.map +1 -0
- package/dist/player/spell.d.ts +146 -0
- package/dist/player/spell.d.ts.map +1 -0
- package/dist/player/spell.js +519 -0
- package/dist/player/spell.js.map +1 -0
- package/dist/player/take-hit.d.ts +87 -0
- package/dist/player/take-hit.d.ts.map +1 -0
- package/dist/player/take-hit.js +99 -0
- package/dist/player/take-hit.js.map +1 -0
- package/dist/player/timed.d.ts +205 -0
- package/dist/player/timed.d.ts.map +1 -0
- package/dist/player/timed.js +310 -0
- package/dist/player/timed.js.map +1 -0
- package/dist/player/types.d.ts +390 -0
- package/dist/player/types.d.ts.map +1 -0
- package/dist/player/types.js +51 -0
- package/dist/player/types.js.map +1 -0
- package/dist/rational.d.ts +99 -0
- package/dist/rational.d.ts.map +1 -0
- package/dist/rational.js +345 -0
- package/dist/rational.js.map +1 -0
- package/dist/rng.d.ts +168 -0
- package/dist/rng.d.ts.map +1 -0
- package/dist/rng.js +404 -0
- package/dist/rng.js.map +1 -0
- package/dist/save/buffer.d.ts +120 -0
- package/dist/save/buffer.d.ts.map +1 -0
- package/dist/save/buffer.js +238 -0
- package/dist/save/buffer.js.map +1 -0
- package/dist/save/compress.d.ts +79 -0
- package/dist/save/compress.d.ts.map +1 -0
- package/dist/save/compress.js +97 -0
- package/dist/save/compress.js.map +1 -0
- package/dist/save/description.d.ts +61 -0
- package/dist/save/description.d.ts.map +1 -0
- package/dist/save/description.js +51 -0
- package/dist/save/description.js.map +1 -0
- package/dist/save/integrity.d.ts +59 -0
- package/dist/save/integrity.d.ts.map +1 -0
- package/dist/save/integrity.js +103 -0
- package/dist/save/integrity.js.map +1 -0
- package/dist/score/display.d.ts +40 -0
- package/dist/score/display.d.ts.map +1 -0
- package/dist/score/display.js +86 -0
- package/dist/score/display.js.map +1 -0
- package/dist/score/score.d.ts +166 -0
- package/dist/score/score.d.ts.map +1 -0
- package/dist/score/score.js +244 -0
- package/dist/score/score.js.map +1 -0
- package/dist/score/types.d.ts +98 -0
- package/dist/score/types.d.ts.map +1 -0
- package/dist/score/types.js +27 -0
- package/dist/score/types.js.map +1 -0
- package/dist/session/boot.d.ts +207 -0
- package/dist/session/boot.d.ts.map +1 -0
- package/dist/session/boot.js +151 -0
- package/dist/session/boot.js.map +1 -0
- package/dist/session/game.d.ts +257 -0
- package/dist/session/game.d.ts.map +1 -0
- package/dist/session/game.js +2880 -0
- package/dist/session/game.js.map +1 -0
- package/dist/session/save.d.ts +847 -0
- package/dist/session/save.d.ts.map +1 -0
- package/dist/session/save.js +1306 -0
- package/dist/session/save.js.map +1 -0
- package/dist/sound/engine.d.ts +146 -0
- package/dist/sound/engine.d.ts.map +1 -0
- package/dist/sound/engine.js +332 -0
- package/dist/sound/engine.js.map +1 -0
- package/dist/sound/index.d.ts +13 -0
- package/dist/sound/index.d.ts.map +1 -0
- package/dist/sound/index.js +13 -0
- package/dist/sound/index.js.map +1 -0
- package/dist/sound/sound-prefs-data.d.ts +10 -0
- package/dist/sound/sound-prefs-data.d.ts.map +1 -0
- package/dist/sound/sound-prefs-data.js +165 -0
- package/dist/sound/sound-prefs-data.js.map +1 -0
- package/dist/sound/types.d.ts +64 -0
- package/dist/sound/types.d.ts.map +1 -0
- package/dist/sound/types.js +23 -0
- package/dist/sound/types.js.map +1 -0
- package/dist/store/bind.d.ts +43 -0
- package/dist/store/bind.d.ts.map +1 -0
- package/dist/store/bind.js +130 -0
- package/dist/store/bind.js.map +1 -0
- package/dist/store/price.d.ts +27 -0
- package/dist/store/price.d.ts.map +1 -0
- package/dist/store/price.js +81 -0
- package/dist/store/price.js.map +1 -0
- package/dist/store/store-cmd.d.ts +51 -0
- package/dist/store/store-cmd.d.ts.map +1 -0
- package/dist/store/store-cmd.js +73 -0
- package/dist/store/store-cmd.js.map +1 -0
- package/dist/store/store.d.ts +156 -0
- package/dist/store/store.d.ts.map +1 -0
- package/dist/store/store.js +616 -0
- package/dist/store/store.js.map +1 -0
- package/dist/store/transact.d.ts +198 -0
- package/dist/store/transact.d.ts.map +1 -0
- package/dist/store/transact.js +383 -0
- package/dist/store/transact.js.map +1 -0
- package/dist/store/types.d.ts +101 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +14 -0
- package/dist/store/types.js.map +1 -0
- package/dist/version.d.ts +25 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +25 -0
- package/dist/version.js.map +1 -0
- package/dist/visuals/engine.d.ts +223 -0
- package/dist/visuals/engine.d.ts.map +1 -0
- package/dist/visuals/engine.js +357 -0
- package/dist/visuals/engine.js.map +1 -0
- package/dist/visuals/glyph-table.d.ts +112 -0
- package/dist/visuals/glyph-table.d.ts.map +1 -0
- package/dist/visuals/glyph-table.js +156 -0
- package/dist/visuals/glyph-table.js.map +1 -0
- package/dist/visuals/grafmode-data.d.ts +4 -0
- package/dist/visuals/grafmode-data.d.ts.map +1 -0
- package/dist/visuals/grafmode-data.js +88 -0
- package/dist/visuals/grafmode-data.js.map +1 -0
- package/dist/visuals/grafmode.d.ts +83 -0
- package/dist/visuals/grafmode.d.ts.map +1 -0
- package/dist/visuals/grafmode.js +82 -0
- package/dist/visuals/grafmode.js.map +1 -0
- package/dist/visuals/index.d.ts +19 -0
- package/dist/visuals/index.d.ts.map +1 -0
- package/dist/visuals/index.js +19 -0
- package/dist/visuals/index.js.map +1 -0
- package/dist/visuals/map-text.d.ts +79 -0
- package/dist/visuals/map-text.d.ts.map +1 -0
- package/dist/visuals/map-text.js +122 -0
- package/dist/visuals/map-text.js.map +1 -0
- package/dist/visuals/pref-expr.d.ts +56 -0
- package/dist/visuals/pref-expr.d.ts.map +1 -0
- package/dist/visuals/pref-expr.js +173 -0
- package/dist/visuals/pref-expr.js.map +1 -0
- package/dist/visuals/prefs.d.ts +280 -0
- package/dist/visuals/prefs.d.ts.map +1 -0
- package/dist/visuals/prefs.js +835 -0
- package/dist/visuals/prefs.js.map +1 -0
- package/dist/visuals/tile-prefs.d.ts +132 -0
- package/dist/visuals/tile-prefs.d.ts.map +1 -0
- package/dist/visuals/tile-prefs.js +105 -0
- package/dist/visuals/tile-prefs.js.map +1 -0
- package/dist/world/chunk.d.ts +195 -0
- package/dist/world/chunk.d.ts.map +1 -0
- package/dist/world/chunk.js +422 -0
- package/dist/world/chunk.js.map +1 -0
- package/dist/world/feature.d.ts +86 -0
- package/dist/world/feature.d.ts.map +1 -0
- package/dist/world/feature.js +153 -0
- package/dist/world/feature.js.map +1 -0
- package/dist/world/flow.d.ts +33 -0
- package/dist/world/flow.d.ts.map +1 -0
- package/dist/world/flow.js +115 -0
- package/dist/world/flow.js.map +1 -0
- package/dist/world/project.d.ts +176 -0
- package/dist/world/project.d.ts.map +1 -0
- package/dist/world/project.js +543 -0
- package/dist/world/project.js.map +1 -0
- package/dist/world/projection.d.ts +100 -0
- package/dist/world/projection.d.ts.map +1 -0
- package/dist/world/projection.js +152 -0
- package/dist/world/projection.js.map +1 -0
- package/dist/world/scatter.d.ts +25 -0
- package/dist/world/scatter.d.ts.map +1 -0
- package/dist/world/scatter.js +54 -0
- package/dist/world/scatter.js.map +1 -0
- package/dist/world/trap.d.ts +84 -0
- package/dist/world/trap.d.ts.map +1 -0
- package/dist/world/trap.js +106 -0
- package/dist/world/trap.js.map +1 -0
- package/dist/world/view.d.ts +60 -0
- package/dist/world/view.d.ts.map +1 -0
- package/dist/world/view.js +436 -0
- package/dist/world/view.js.map +1 -0
- package/dist/z-queue.d.ts +133 -0
- package/dist/z-queue.d.ts.map +1 -0
- package/dist/z-queue.js +283 -0
- package/dist/z-queue.js.map +1 -0
- package/package.json +75 -0
- package/src/agent/act.ts +114 -0
- package/src/agent/controller.ts +109 -0
- package/src/agent/events.ts +47 -0
- package/src/agent/index.ts +36 -0
- package/src/agent/perceive.ts +440 -0
- package/src/agent/types.ts +464 -0
- package/src/bitflag.ts +536 -0
- package/src/cmd.ts +547 -0
- package/src/color.ts +267 -0
- package/src/combat/brand-slay.ts +360 -0
- package/src/combat/hit.ts +471 -0
- package/src/combat/index.ts +15 -0
- package/src/combat/melee.ts +728 -0
- package/src/combat/mon-melee.ts +1153 -0
- package/src/combat/ranged.ts +397 -0
- package/src/constants.ts +324 -0
- package/src/dice.ts +467 -0
- package/src/effects/effect-choice.ts +32 -0
- package/src/effects/effect-info.ts +859 -0
- package/src/effects/effect.ts +560 -0
- package/src/effects/handlers.ts +452 -0
- package/src/effects/interpreter.ts +603 -0
- package/src/events.ts +317 -0
- package/src/expression.ts +360 -0
- package/src/game/cave-cmd.ts +1147 -0
- package/src/game/char-sheet.ts +557 -0
- package/src/game/chest.ts +348 -0
- package/src/game/context.ts +1218 -0
- package/src/game/curse-tick.ts +130 -0
- package/src/game/describe.ts +62 -0
- package/src/game/display.ts +838 -0
- package/src/game/dump-level.ts +114 -0
- package/src/game/effect-attack.ts +746 -0
- package/src/game/effect-detect.ts +542 -0
- package/src/game/effect-env.ts +252 -0
- package/src/game/effect-game-env.ts +86 -0
- package/src/game/effect-general.ts +1122 -0
- package/src/game/effect-item.ts +999 -0
- package/src/game/effect-melee.ts +557 -0
- package/src/game/effect-mon-origin.ts +196 -0
- package/src/game/effect-monster.ts +310 -0
- package/src/game/effect-summon.ts +161 -0
- package/src/game/effect-teleport.ts +645 -0
- package/src/game/effect-terrain.ts +881 -0
- package/src/game/energy.ts +61 -0
- package/src/game/equip-cmp.ts +476 -0
- package/src/game/floor.ts +524 -0
- package/src/game/gear.ts +1352 -0
- package/src/game/harness.ts +270 -0
- package/src/game/history.ts +78 -0
- package/src/game/ignore-cmd.ts +68 -0
- package/src/game/inscription-confirm.ts +115 -0
- package/src/game/known.ts +960 -0
- package/src/game/loop.ts +671 -0
- package/src/game/lore-color.ts +108 -0
- package/src/game/mon-cast.ts +409 -0
- package/src/game/mon-cmd.ts +767 -0
- package/src/game/mon-death.ts +459 -0
- package/src/game/mon-group.ts +368 -0
- package/src/game/mon-list.ts +213 -0
- package/src/game/mon-message.ts +359 -0
- package/src/game/mon-place.ts +1012 -0
- package/src/game/mon-ranged.ts +405 -0
- package/src/game/mon-shape.ts +161 -0
- package/src/game/mon-side.ts +511 -0
- package/src/game/monster-turn.ts +1750 -0
- package/src/game/obj-cmd.ts +1970 -0
- package/src/game/obj-list.ts +302 -0
- package/src/game/object-inspect.ts +162 -0
- package/src/game/pickup.ts +483 -0
- package/src/game/player-path.ts +1434 -0
- package/src/game/player-side.ts +555 -0
- package/src/game/player-turn.ts +852 -0
- package/src/game/project-cast.ts +766 -0
- package/src/game/project-feat.ts +386 -0
- package/src/game/project-monster.ts +407 -0
- package/src/game/project-obj.ts +298 -0
- package/src/game/project-player.ts +236 -0
- package/src/game/quest.ts +248 -0
- package/src/game/ranged-cmd.ts +417 -0
- package/src/game/scheduler.ts +150 -0
- package/src/game/spell-cmd.ts +404 -0
- package/src/game/spoil.ts +562 -0
- package/src/game/steal.ts +169 -0
- package/src/game/take-hit-hooks.ts +152 -0
- package/src/game/target-loop.ts +501 -0
- package/src/game/target.ts +424 -0
- package/src/game/thrust.ts +174 -0
- package/src/game/trap.ts +791 -0
- package/src/game/ui-entry.ts +2075 -0
- package/src/game/wizard.ts +1760 -0
- package/src/game/world.ts +786 -0
- package/src/gen/cave.ts +2858 -0
- package/src/gen/gen-monster.ts +592 -0
- package/src/gen/generate.ts +523 -0
- package/src/gen/room.ts +2213 -0
- package/src/gen/util.ts +1958 -0
- package/src/generated/dun-profiles.ts +30 -0
- package/src/generated/effects.ts +241 -0
- package/src/generated/elements.ts +62 -0
- package/src/generated/equip-slots.ts +36 -0
- package/src/generated/history-types.ts +34 -0
- package/src/generated/ignore-types.ts +66 -0
- package/src/generated/index.ts +33 -0
- package/src/generated/kind-flags.ts +44 -0
- package/src/generated/message.ts +320 -0
- package/src/generated/mon-message.ts +138 -0
- package/src/generated/mon-race-flags.ts +182 -0
- package/src/generated/mon-spells.ts +198 -0
- package/src/generated/mon-temp-flags.ts +34 -0
- package/src/generated/mon-timed.ts +34 -0
- package/src/generated/object-flags.ts +95 -0
- package/src/generated/object-modifiers.ts +43 -0
- package/src/generated/options.ts +104 -0
- package/src/generated/origins.ts +64 -0
- package/src/generated/parser-errors.ts +140 -0
- package/src/generated/player-flags.ts +48 -0
- package/src/generated/player-timed.ts +118 -0
- package/src/generated/projections.ts +103 -0
- package/src/generated/randart-properties.ts +202 -0
- package/src/generated/room-flags.ts +21 -0
- package/src/generated/rooms.ts +50 -0
- package/src/generated/square-flags.ts +56 -0
- package/src/generated/stats.ts +22 -0
- package/src/generated/terrain-flags.ts +76 -0
- package/src/generated/terrain.ts +62 -0
- package/src/generated/trap-flags.ts +42 -0
- package/src/generated/tvals.ts +84 -0
- package/src/generated/ui-entry-renderers.ts +24 -0
- package/src/guard.ts +70 -0
- package/src/host/args.ts +334 -0
- package/src/host/bridge.ts +193 -0
- package/src/host/index.ts +18 -0
- package/src/host/io.ts +239 -0
- package/src/host/memory.ts +134 -0
- package/src/host/raw.ts +190 -0
- package/src/index.ts +250 -0
- package/src/loc.ts +157 -0
- package/src/mod/hooks.ts +278 -0
- package/src/mod/ids.ts +390 -0
- package/src/mod/registry-host.ts +258 -0
- package/src/mod/save-blocks.ts +787 -0
- package/src/mod/vocabulary.ts +0 -0
- package/src/mon/bind.ts +899 -0
- package/src/mon/desc.ts +212 -0
- package/src/mon/knowledge-groups.ts +164 -0
- package/src/mon/lore-describe.ts +1414 -0
- package/src/mon/lore.ts +306 -0
- package/src/mon/make.ts +422 -0
- package/src/mon/monster.ts +161 -0
- package/src/mon/predicate.ts +220 -0
- package/src/mon/project-mon.ts +855 -0
- package/src/mon/spell.ts +418 -0
- package/src/mon/steal.ts +246 -0
- package/src/mon/summon.ts +145 -0
- package/src/mon/take-hit.ts +195 -0
- package/src/mon/timed.ts +300 -0
- package/src/mon/types.ts +286 -0
- package/src/msg.ts +146 -0
- package/src/obj/artifact-fake.ts +63 -0
- package/src/obj/artifact-known.ts +69 -0
- package/src/obj/bind.ts +1345 -0
- package/src/obj/chest.ts +249 -0
- package/src/obj/desc.ts +699 -0
- package/src/obj/effects-info.ts +349 -0
- package/src/obj/flavor.ts +256 -0
- package/src/obj/ignore.ts +387 -0
- package/src/obj/knowledge.ts +1577 -0
- package/src/obj/known-object.ts +718 -0
- package/src/obj/make.ts +1367 -0
- package/src/obj/object-info.ts +1737 -0
- package/src/obj/object.ts +1296 -0
- package/src/obj/power.ts +674 -0
- package/src/obj/randart-build.ts +1705 -0
- package/src/obj/randart-data.ts +1344 -0
- package/src/obj/randart.ts +552 -0
- package/src/obj/randname.ts +128 -0
- package/src/obj/recharge.ts +62 -0
- package/src/obj/types.ts +559 -0
- package/src/obj/value.ts +215 -0
- package/src/player/abilities.ts +142 -0
- package/src/player/best-digger.ts +118 -0
- package/src/player/bind.ts +1021 -0
- package/src/player/birth.ts +794 -0
- package/src/player/calcs.ts +1522 -0
- package/src/player/combat-regen.ts +33 -0
- package/src/player/exp.ts +275 -0
- package/src/player/history.ts +211 -0
- package/src/player/options.ts +244 -0
- package/src/player/player.ts +356 -0
- package/src/player/shape-lore.ts +250 -0
- package/src/player/spell.ts +627 -0
- package/src/player/take-hit.ts +173 -0
- package/src/player/timed.ts +482 -0
- package/src/player/types.ts +415 -0
- package/src/rational.ts +388 -0
- package/src/rng.ts +476 -0
- package/src/save/buffer.ts +287 -0
- package/src/save/compress.ts +132 -0
- package/src/save/description.ts +70 -0
- package/src/save/integrity.ts +133 -0
- package/src/score/display.ts +125 -0
- package/src/score/score.ts +341 -0
- package/src/score/types.ts +104 -0
- package/src/session/boot.ts +338 -0
- package/src/session/game.ts +3712 -0
- package/src/session/save.ts +2074 -0
- package/src/sound/engine.ts +375 -0
- package/src/sound/index.ts +13 -0
- package/src/sound/sound-prefs-data.ts +173 -0
- package/src/sound/types.ts +68 -0
- package/src/store/bind.ts +145 -0
- package/src/store/price.ts +97 -0
- package/src/store/store-cmd.ts +73 -0
- package/src/store/store.ts +723 -0
- package/src/store/transact.ts +644 -0
- package/src/store/types.ts +110 -0
- package/src/version.ts +26 -0
- package/src/visuals/engine.ts +444 -0
- package/src/visuals/glyph-table.ts +191 -0
- package/src/visuals/grafmode-data.ts +90 -0
- package/src/visuals/grafmode.ts +123 -0
- package/src/visuals/index.ts +19 -0
- package/src/visuals/map-text.ts +152 -0
- package/src/visuals/pref-expr.ts +182 -0
- package/src/visuals/prefs.ts +981 -0
- package/src/visuals/tile-prefs.ts +183 -0
- package/src/world/chunk.ts +531 -0
- package/src/world/feature.ts +215 -0
- package/src/world/flow.ts +128 -0
- package/src/world/project.ts +687 -0
- package/src/world/projection.ts +228 -0
- package/src/world/scatter.ts +72 -0
- package/src/world/trap.ts +155 -0
- package/src/world/view.ts +513 -0
- package/src/z-queue.ts +300 -0
package/src/gen/room.ts
ADDED
|
@@ -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
|
+
}
|