@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
|
@@ -0,0 +1,1530 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object commands, ported from reference/src/cmd-obj.c (Angband 4.2.6) with
|
|
3
|
+
* the obj-gear.c inventory verbs they sit on: take off / wield / drop, and
|
|
4
|
+
* the use family (eat, quaff, read, use staff, aim wand, zap rod, activate)
|
|
5
|
+
* running each object's effect chain through the effect interpreter with a
|
|
6
|
+
* player source - the same stack monster spells cast through.
|
|
7
|
+
*
|
|
8
|
+
* Knowledge rides on the ported FlavorKnowledge (obj/knowledge.ts):
|
|
9
|
+
* unaware flavored items aim at random when they secretly need a direction,
|
|
10
|
+
* single-use items learn their flavor on use, devices are marked tried.
|
|
11
|
+
* The deeper known-object bookkeeping (obj->known twins, work_obj copies
|
|
12
|
+
* for messaging) is knowledge/UI work (#24/#25) and is replaced by hooks.
|
|
13
|
+
*
|
|
14
|
+
* Inscribe/uninscribe/refill (fuel) are ported below (cmd-obj.c
|
|
15
|
+
* do_cmd_inscribe/do_cmd_uninscribe/do_cmd_refill + refill_lamp,
|
|
16
|
+
* obj-util.c obj_can_refill/obj_has_inscrip). Autoinscribe
|
|
17
|
+
* (do_cmd_autoinscribe/apply_autoinscription) applies the per-kind
|
|
18
|
+
* note_aware/note_unaware registry (obj/knowledge.ts AutoinscriptionRegistry,
|
|
19
|
+
* wired through ObjCmdDeps.autoNote by session/game.ts). The separate
|
|
20
|
+
* rune-based autoinscription (runes_autoinscribe, obj-ignore.c L217) rides the
|
|
21
|
+
* rune knowledge system and stays deferred (#24).
|
|
22
|
+
*
|
|
23
|
+
* DEFERRED with their subsystems (ledgered in game-obj-cmd.yaml):
|
|
24
|
+
* cast/study (player spells #22), the glyph-of-warding push_object
|
|
25
|
+
* interaction (traps #21), command repetition, and the !t take-off
|
|
26
|
+
* confirmation prompt (get_check, UI).
|
|
27
|
+
*/
|
|
28
|
+
import { EFFECT_ENTRIES, EQUIP_SLOT_ENTRIES, OF, TMD } from "../generated/index.js";
|
|
29
|
+
import { DDD } from "../loc.js";
|
|
30
|
+
import { SKILL } from "../player/types.js";
|
|
31
|
+
import { EffectBuilder } from "../effects/effect.js";
|
|
32
|
+
import { sourcePlayer } from "../effects/interpreter.js";
|
|
33
|
+
import { objectPackTotal, tvalIsEdible, tvalIsFuel, tvalIsLauncher, tvalIsLight, tvalIsMeleeWeapon, tvalIsPotion, tvalIsRing, tvalIsRod, tvalIsScroll, tvalIsStaff, tvalIsWand, tvalIsWearable, tvalCanHaveCharges, tvalCanHaveTimeout, } from "../obj/object.js";
|
|
34
|
+
import { FlavorKnowledge, NOOP_FLAVOR_AWARE_DEPS, buildRuneList, objectHasRune, playerKnowsRune, } from "../obj/knowledge.js";
|
|
35
|
+
import { ignoreItemOk } from "../obj/ignore.js";
|
|
36
|
+
import { dropNear, floorObjectForUse, floorPile } from "./floor.js";
|
|
37
|
+
import { calcInventory, combinePack, gearGet, gearObjectForUse, gearToLabel, invenCarry, invenCarryNum, objectSplit, packIsOverfull, packTotalSuppressed, packTotalView, wieldObject, wieldSlot, } from "./gear.js";
|
|
38
|
+
import { checkForInscrip } from "./pickup.js";
|
|
39
|
+
import { disturb } from "./player-path.js";
|
|
40
|
+
import { buildEffectContext } from "./effect-env.js";
|
|
41
|
+
import { attachGameEnv } from "./effect-game-env.js";
|
|
42
|
+
import { describeObject } from "./describe.js";
|
|
43
|
+
import { ODESC, objDescNameFormat } from "../obj/desc.js";
|
|
44
|
+
import { substituteTimedMessage } from "../player/timed.js";
|
|
45
|
+
import { squareIsSeen } from "../world/view.js";
|
|
46
|
+
import { updatePlayerObjectKnowledge } from "./known.js";
|
|
47
|
+
import { targetFix, targetGet, targetOkay, targetRelease } from "./target.js";
|
|
48
|
+
/** enum use (cmd-obj.c). */
|
|
49
|
+
export const USE = { TIMEOUT: 0, CHARGE: 1, SINGLE: 2 };
|
|
50
|
+
/** Build calc_inventory options from the object-command deps (gap 4.1). */
|
|
51
|
+
function calcInvOpts(state, deps) {
|
|
52
|
+
const o = {
|
|
53
|
+
/* object_is_equipped(p->body, old_pack[i]) (player-calcs.c:1227): wielding
|
|
54
|
+
* an item moves it out of the pack, which must not read as a re-arrangement.
|
|
55
|
+
* This is the path where that happens, so the predicate belongs here. */
|
|
56
|
+
isEquipped: (handle) => state.actor.player.equipment.includes(handle),
|
|
57
|
+
};
|
|
58
|
+
if (deps.env?.msg)
|
|
59
|
+
o.msg = deps.env.msg;
|
|
60
|
+
if (deps.rogueLike)
|
|
61
|
+
o.rogueLike = deps.rogueLike;
|
|
62
|
+
if (deps.characterDungeon)
|
|
63
|
+
o.characterDungeon = deps.characterDungeon;
|
|
64
|
+
const at = deps.ammoTval?.() ?? state.playerState?.ammoTval;
|
|
65
|
+
if (at !== undefined)
|
|
66
|
+
o.ammoTval = at;
|
|
67
|
+
if (deps.objectValue)
|
|
68
|
+
o.objectValue = deps.objectValue;
|
|
69
|
+
return o;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The combine_pack / pack_overflow seams for the command handlers: the message
|
|
73
|
+
* sink, the calc_inventory inputs, and the drop_near environment
|
|
74
|
+
* pack_overflow's drop needs (deps.floorEnv is the same one inven_drop uses).
|
|
75
|
+
*/
|
|
76
|
+
function packOpts(state, deps) {
|
|
77
|
+
const o = { calcInv: calcInvOpts(state, deps) };
|
|
78
|
+
if (deps.env?.msg)
|
|
79
|
+
o.msg = deps.env.msg;
|
|
80
|
+
if (deps.floorEnv)
|
|
81
|
+
o.floorEnv = deps.floorEnv;
|
|
82
|
+
return o;
|
|
83
|
+
}
|
|
84
|
+
function stackLimits(constants) {
|
|
85
|
+
return {
|
|
86
|
+
quiverSlotSize: constants.quiverSlotSize,
|
|
87
|
+
thrownQuiverMult: constants.thrownQuiverMult,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/* ------------------------------------------------------------------ *
|
|
91
|
+
* obj-gear.c inventory verbs.
|
|
92
|
+
* ------------------------------------------------------------------ */
|
|
93
|
+
/**
|
|
94
|
+
* inven_takeoff (obj-gear.c L1033): de-equip an object back into the pack.
|
|
95
|
+
* Returns whether the handle was equipped. (Upstream does not re-combine;
|
|
96
|
+
* the caller runs combine_pack, which the port's pack model does lazily on
|
|
97
|
+
* the next inven_carry.)
|
|
98
|
+
*/
|
|
99
|
+
export function invenTakeoff(state, handle) {
|
|
100
|
+
const player = state.actor.player;
|
|
101
|
+
const slot = player.equipment.indexOf(handle);
|
|
102
|
+
if (slot < 0)
|
|
103
|
+
return false;
|
|
104
|
+
player.equipment[slot] = 0;
|
|
105
|
+
state.gear.pack.push(handle);
|
|
106
|
+
state.updateBonuses?.(); /* PU_BONUS */
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
/** calcInv with the shared msg sink filled in when the caller left it out. */
|
|
110
|
+
function overflowCalcInv(opts) {
|
|
111
|
+
const base = { ...opts.calcInv };
|
|
112
|
+
if (!base.msg && opts.msg)
|
|
113
|
+
base.msg = opts.msg;
|
|
114
|
+
return base;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* pack_overflow (obj-gear.c L1345-1390): when the pack holds more than
|
|
118
|
+
* pack_size slots, shed one item onto the floor. `handle` is upstream's `obj`
|
|
119
|
+
* argument - the item to shed, normally whatever displaced into the pack; 0 is
|
|
120
|
+
* upstream's NULL, meaning "shed the last item of the inventory listing".
|
|
121
|
+
* Returns the object that left the pack, or null when nothing overflowed.
|
|
122
|
+
*
|
|
123
|
+
* The C's three messages and their order are reproduced exactly: the warning,
|
|
124
|
+
* then "You drop X." with X described BEFORE the excise, then the drop, then
|
|
125
|
+
* "You no longer have X."
|
|
126
|
+
*
|
|
127
|
+
* For the NULL case, upkeep->inven[] is represented by the derived,
|
|
128
|
+
* earlier_object-sorted gear.inven view (player-calcs.c:1191-1222); gear.pack
|
|
129
|
+
* remains the raw master-gear order and must not select the victim.
|
|
130
|
+
*/
|
|
131
|
+
export function packOverflow(state, handle, constants, opts = {}) {
|
|
132
|
+
/* packSlotsUsed's public Constants type includes unrelated z_info fields;
|
|
133
|
+
* only the PackOverflowConstants subset is read on this path. */
|
|
134
|
+
if (!packIsOverfull(state.gear, constants))
|
|
135
|
+
return null;
|
|
136
|
+
/* Disturbing (L1353). */
|
|
137
|
+
disturb(state);
|
|
138
|
+
/* Warning (L1356). */
|
|
139
|
+
opts.msg?.("Your pack overflows!");
|
|
140
|
+
/* Drop the last inventory item unless requested otherwise (L1359-1366). */
|
|
141
|
+
const victim = handle !== 0
|
|
142
|
+
? handle
|
|
143
|
+
: (state.gear.inven?.[state.gear.inven.length - 1] ?? 0);
|
|
144
|
+
const obj = gearGet(state.gear, victim);
|
|
145
|
+
/* Upstream asserts obj != NULL here (L1369). The port can reach a stale
|
|
146
|
+
* handle where upstream reads freed memory: combine_pack (which runs just
|
|
147
|
+
* before every caller's pack_overflow) may have absorbed the displaced item
|
|
148
|
+
* into an earlier stack, which upstream frees while still holding the
|
|
149
|
+
* pointer. Absorbing shrinks the pack, so an overfull pack with a stale
|
|
150
|
+
* handle is a corner the C does not define; the port sheds nothing. */
|
|
151
|
+
if (!obj)
|
|
152
|
+
return null;
|
|
153
|
+
/* Describe (L1372-1374) BEFORE the excise, so the count is the pre-drop one. */
|
|
154
|
+
const name = describeObject(state, obj);
|
|
155
|
+
/* Message (L1377). */
|
|
156
|
+
opts.msg?.(`You drop ${name}.`);
|
|
157
|
+
/* Excise the object and drop it (carefully) near the player (L1379-1380).
|
|
158
|
+
* gear_excise_object re-runs calc_inventory (obj-gear.c L497). */
|
|
159
|
+
const { obj: dropped } = gearObjectForUse(state.gear, state.actor.player, victim, obj.number);
|
|
160
|
+
calcInventory(state.gear, constants, overflowCalcInv(opts));
|
|
161
|
+
/* drop_near(cave, &obj, 0, player->grid, false, true): prefer_pile. */
|
|
162
|
+
dropNear(state, dropped, 0, state.actor.grid, false, true, opts.floorEnv ?? {});
|
|
163
|
+
/* Describe (L1383). */
|
|
164
|
+
opts.msg?.(`You no longer have ${name}.`);
|
|
165
|
+
state.updateBonuses?.(); /* gear_excise_object's PU_BONUS (obj-gear.c L500). */
|
|
166
|
+
return dropped;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* inven_wield (obj-gear.c L931-1017): wield a pack object into `intoSlot`,
|
|
170
|
+
* taking off whatever occupies it first, then combine_pack + pack_overflow so
|
|
171
|
+
* a displaced item that does not fit is dropped (L1009-1010). Returns the
|
|
172
|
+
* slot, or -1 when the object cannot be worn. Read
|
|
173
|
+
* `state.actor.player.equipment[slot]` for the handle actually worn - a wield
|
|
174
|
+
* out of a stack equips a FRESH split, not `handle` (L947-968).
|
|
175
|
+
*
|
|
176
|
+
* The slot is an ARGUMENT upstream (`inven_wield(struct object *obj, int slot)`,
|
|
177
|
+
* obj-gear.c:931) and is NOT recomputed inside: do_cmd_wield picks it, and for a
|
|
178
|
+
* ring the player picks it (cmd-obj.c:298-311). Re-deriving it with wield_slot
|
|
179
|
+
* here is what made the third ring always land in the same hand. `intoSlot` is
|
|
180
|
+
* optional only so the pre-existing worldless callers keep the wield_slot
|
|
181
|
+
* default; every in-play caller passes the slot it decided.
|
|
182
|
+
*
|
|
183
|
+
* The MSG_WIELD line and the OF_STICKY warning (L986-1008) live here rather
|
|
184
|
+
* than in the command handler because upstream emits them BEFORE combine_pack,
|
|
185
|
+
* while do_cmd_wield's "You were wielding ..." line comes AFTER it (cmd-obj.c
|
|
186
|
+
* L346-352) and so reads the post-combine gear label.
|
|
187
|
+
*/
|
|
188
|
+
export function invenWield(state, handle, constants, opts = {}, intoSlot) {
|
|
189
|
+
const player = state.actor.player;
|
|
190
|
+
const obj = gearGet(state.gear, handle);
|
|
191
|
+
if (!obj)
|
|
192
|
+
return -1;
|
|
193
|
+
const slot = intoSlot !== undefined
|
|
194
|
+
? intoSlot
|
|
195
|
+
: wieldSlot(player.body, obj.tval, player.equipment);
|
|
196
|
+
if (slot < 0 || slot >= player.body.count)
|
|
197
|
+
return -1;
|
|
198
|
+
/* `old` (L933): the slot's current occupant. Upstream just overwrites
|
|
199
|
+
* body.slots[slot].obj, which leaves `old` in p->gear as a pack item; the
|
|
200
|
+
* port's equipment[]/pack split needs the move spelled out. */
|
|
201
|
+
const oldHandle = player.equipment[slot] ?? 0;
|
|
202
|
+
if (oldHandle !== 0)
|
|
203
|
+
invenTakeoff(state, oldHandle);
|
|
204
|
+
const worn = wieldObject(state.gear, player, handle, state.runeEnv, "inven_wield", slot);
|
|
205
|
+
if (worn < 0)
|
|
206
|
+
return worn;
|
|
207
|
+
const wornHandle = player.equipment[worn] ?? 0;
|
|
208
|
+
const wornObj = gearGet(state.gear, wornHandle);
|
|
209
|
+
/* Where is the item now, and the message (L991-1006). */
|
|
210
|
+
if (wornObj && opts.msg) {
|
|
211
|
+
const verb = tvalIsMeleeWeapon(wornObj.tval)
|
|
212
|
+
? "You are wielding"
|
|
213
|
+
: tvalIsLauncher(wornObj.tval)
|
|
214
|
+
? "You are shooting with"
|
|
215
|
+
: tvalIsLight(wornObj.tval)
|
|
216
|
+
? "Your light source is"
|
|
217
|
+
: "You are wearing";
|
|
218
|
+
opts.msg(`${verb} ${describeObject(state, wornObj)} (${gearLabelFor(state, wornHandle)}).`);
|
|
219
|
+
/* Sticky flag gets a special mention (L1008). */
|
|
220
|
+
if (wornObj.flags.has(OF.STICKY)) {
|
|
221
|
+
opts.msg("Oops! It feels deathly cold!");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/* See if we have to overflow the pack (L1009-1010). */
|
|
225
|
+
combinePack(state.gear, constants, overflowCalcInv(opts));
|
|
226
|
+
packOverflow(state, oldHandle, constants, opts);
|
|
227
|
+
/* object_learn_on_wield's player_learn_rune tail-calls
|
|
228
|
+
* update_player_object_knowledge (obj-knowledge.c L1373): the wield learns the
|
|
229
|
+
* obvious runes, and the sweep is what turns that into cross-object awareness
|
|
230
|
+
* (e.g. a worn Ring of Strength becoming flavour-aware - KN-03). */
|
|
231
|
+
updatePlayerObjectKnowledge(state);
|
|
232
|
+
state.updateBonuses?.(); /* PU_BONUS */
|
|
233
|
+
return worn;
|
|
234
|
+
}
|
|
235
|
+
/** cmd_get_item's prompt for the second wield question (cmd-obj.c:300). */
|
|
236
|
+
export const WIELD_REPLACE_RING_PROMPT = "Replace which ring? ";
|
|
237
|
+
/** cmd_get_item's error for it (cmd-obj.c:301) - a "please report" paranoia line. */
|
|
238
|
+
export const WIELD_REPLACE_RING_ERROR = "Error in do_cmd_wield(), please report.";
|
|
239
|
+
export function wieldRingChoice(state, obj) {
|
|
240
|
+
const player = state.actor.player;
|
|
241
|
+
if (!tvalIsRing(obj.tval))
|
|
242
|
+
return null;
|
|
243
|
+
const slot = wieldSlot(player.body, obj.tval, player.equipment);
|
|
244
|
+
if (slot < 0 || slot >= player.body.count)
|
|
245
|
+
return null;
|
|
246
|
+
/* "If the slot is open, wield and be done" (cmd-obj.c:291-295) - asked BEFORE
|
|
247
|
+
* the ring branch, so an empty hand skips the question entirely. */
|
|
248
|
+
if ((player.equipment[slot] ?? 0) === 0)
|
|
249
|
+
return null;
|
|
250
|
+
const slots = [];
|
|
251
|
+
for (let i = 0; i < player.body.count; i++) {
|
|
252
|
+
const handle = player.equipment[i] ?? 0;
|
|
253
|
+
if (!handle)
|
|
254
|
+
continue;
|
|
255
|
+
const worn = gearGet(state.gear, handle);
|
|
256
|
+
/* USE_EQUIP filtered by tval_is_ring: the worn rings, both of them. */
|
|
257
|
+
if (worn && tvalIsRing(worn.tval))
|
|
258
|
+
slots.push(i);
|
|
259
|
+
}
|
|
260
|
+
if (slots.length === 0)
|
|
261
|
+
return null;
|
|
262
|
+
return {
|
|
263
|
+
prompt: WIELD_REPLACE_RING_PROMPT,
|
|
264
|
+
error: WIELD_REPLACE_RING_ERROR,
|
|
265
|
+
slots,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
export function wieldTakeoffConfirm(state, slot) {
|
|
269
|
+
const handle = state.actor.player.equipment[slot] ?? 0;
|
|
270
|
+
if (!handle)
|
|
271
|
+
return null;
|
|
272
|
+
const displaced = gearGet(state.gear, handle);
|
|
273
|
+
if (!displaced)
|
|
274
|
+
return null;
|
|
275
|
+
const count = checkForInscrip(displaced, "!t");
|
|
276
|
+
if (!count)
|
|
277
|
+
return null;
|
|
278
|
+
const name = describeObject(state, displaced, ODESC.PREFIX | ODESC.FULL);
|
|
279
|
+
return { prompt: `Really take off ${name}? `, count };
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* inven_drop (obj-gear.c L1078): drop amt of a carried object near the
|
|
283
|
+
* player (equipment is taken off first). Returns null when nothing was dropped.
|
|
284
|
+
*
|
|
285
|
+
* The two messages stay at the caller (the command handler), but `noneLeft` and
|
|
286
|
+
* `wasEquipped` come back with the result because upstream's own message block
|
|
287
|
+
* (L1120-1165) branches on both.
|
|
288
|
+
*/
|
|
289
|
+
export function invenDrop(state, handle, amt, floorEnv = {}) {
|
|
290
|
+
if (amt <= 0)
|
|
291
|
+
return null;
|
|
292
|
+
const obj = gearGet(state.gear, handle);
|
|
293
|
+
if (!obj)
|
|
294
|
+
return null;
|
|
295
|
+
if (amt > obj.number)
|
|
296
|
+
amt = obj.number;
|
|
297
|
+
/* Take off equipment, don't combine. */
|
|
298
|
+
let wasEquipped = false;
|
|
299
|
+
if (state.actor.player.equipment.includes(handle)) {
|
|
300
|
+
wasEquipped = true;
|
|
301
|
+
invenTakeoff(state, handle);
|
|
302
|
+
}
|
|
303
|
+
const { obj: dropped, noneLeft } = gearObjectForUse(state.gear, state.actor.player, handle, amt);
|
|
304
|
+
dropNear(state, dropped, 0, state.actor.grid, false, true, floorEnv);
|
|
305
|
+
return { dropped, noneLeft, wasEquipped };
|
|
306
|
+
}
|
|
307
|
+
/* ------------------------------------------------------------------ *
|
|
308
|
+
* cmd-obj.c use machinery.
|
|
309
|
+
* ------------------------------------------------------------------ */
|
|
310
|
+
/**
|
|
311
|
+
* gear_to_label (obj-gear.c:443) with the equipment arm supplied: this module's
|
|
312
|
+
* callers can be holding an equipped object (takeoff, the "you cannot remove"
|
|
313
|
+
* refusals), so the body slots are passed in. One implementation, game/gear.ts.
|
|
314
|
+
*/
|
|
315
|
+
function gearLabelFor(state, handle) {
|
|
316
|
+
return gearToLabel(state.gear, handle, state.actor.player.equipment);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* gear_to_label for an object object_pack_total handed back by reference, which
|
|
320
|
+
* the port must map to a handle first.
|
|
321
|
+
*/
|
|
322
|
+
function packLabelFor(state, obj) {
|
|
323
|
+
for (const handle of state.gear.pack) {
|
|
324
|
+
if (state.gear.store.get(handle) === obj)
|
|
325
|
+
return gearLabelFor(state, handle);
|
|
326
|
+
}
|
|
327
|
+
return "";
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* equip_describe (obj-gear.c L320-332): how a slot's occupant is being used,
|
|
331
|
+
* for the "You cannot remove the X you are Y." refusal. A heavy weapon or
|
|
332
|
+
* launcher reads as the slot's heavy wording instead, and a named slot (rings,
|
|
333
|
+
* hands) interpolates the slot name into its describe template.
|
|
334
|
+
*/
|
|
335
|
+
function equipDescribe(state, slot) {
|
|
336
|
+
const p = state.actor.player;
|
|
337
|
+
const bodySlot = p.body.slots[slot];
|
|
338
|
+
if (!bodySlot)
|
|
339
|
+
return "";
|
|
340
|
+
const entry = EQUIP_SLOT_ENTRIES.find((e) => e.name === bodySlot.type);
|
|
341
|
+
if (!entry)
|
|
342
|
+
return "";
|
|
343
|
+
const ps = state.playerState;
|
|
344
|
+
if (bodySlot.type === "WEAPON" && (ps?.heavyWield || ps?.heavyShoot)) {
|
|
345
|
+
return entry.heavyDescribe;
|
|
346
|
+
}
|
|
347
|
+
if (entry.named)
|
|
348
|
+
return entry.describe.replace("%s", bodySlot.name);
|
|
349
|
+
return entry.describe;
|
|
350
|
+
}
|
|
351
|
+
/** beam_chance (cmd-obj.c L112). */
|
|
352
|
+
export function beamChance(tval) {
|
|
353
|
+
if (tvalIsWand(tval))
|
|
354
|
+
return 20;
|
|
355
|
+
if (tvalIsRod(tval))
|
|
356
|
+
return 10;
|
|
357
|
+
return 0;
|
|
358
|
+
}
|
|
359
|
+
/** The difficulty level of a used object (artifact / activation / kind). */
|
|
360
|
+
function objectLevel(obj) {
|
|
361
|
+
if (obj.artifact)
|
|
362
|
+
return obj.artifact.level;
|
|
363
|
+
if (obj.activation)
|
|
364
|
+
return obj.activation.level;
|
|
365
|
+
return obj.kind.level;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* get_use_device_chance (obj-util.c L930): failure rate out of 1000 for
|
|
369
|
+
* using a device, from the device skill against the item level.
|
|
370
|
+
*/
|
|
371
|
+
export function getUseDeviceChance(state, obj) {
|
|
372
|
+
const skill = state.actor.combat.skills[SKILL.DEVICE] ?? 0;
|
|
373
|
+
const lev = objectLevel(obj);
|
|
374
|
+
const x = 2 * (skill - lev) + 1;
|
|
375
|
+
let fail = -370 * x;
|
|
376
|
+
fail = Math.trunc(fail / (5 + Math.abs(x)));
|
|
377
|
+
fail += 380;
|
|
378
|
+
return fail;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* check_devices (cmd-obj.c L59): can the device be used this turn?
|
|
382
|
+
* Returns 1 usable, 0 failed-but-retryable, -1 unusable.
|
|
383
|
+
*/
|
|
384
|
+
export function checkDevices(state, obj, env = {}) {
|
|
385
|
+
let action;
|
|
386
|
+
let what = null;
|
|
387
|
+
if (tvalIsRod(obj.tval)) {
|
|
388
|
+
action = "zap the rod";
|
|
389
|
+
}
|
|
390
|
+
else if (tvalIsWand(obj.tval)) {
|
|
391
|
+
action = "use the wand";
|
|
392
|
+
what = "wand";
|
|
393
|
+
}
|
|
394
|
+
else if (tvalIsStaff(obj.tval)) {
|
|
395
|
+
action = "use the staff";
|
|
396
|
+
what = "staff";
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
action = "activate it";
|
|
400
|
+
}
|
|
401
|
+
/* Notice empty staffs / wands. */
|
|
402
|
+
if (what && obj.pval <= 0) {
|
|
403
|
+
env.msg?.(`The ${what} has no charges left.`);
|
|
404
|
+
return -1;
|
|
405
|
+
}
|
|
406
|
+
const fail = getUseDeviceChance(state, obj);
|
|
407
|
+
if (state.rng.randint1(1000) < fail) {
|
|
408
|
+
env.msg?.(`You failed to ${action} properly.`);
|
|
409
|
+
return fail < 1001 ? 0 : -1;
|
|
410
|
+
}
|
|
411
|
+
return 1;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* number_charging (obj-util.c L1020): how many rods in a stack are still
|
|
415
|
+
* charging, from the average charge time.
|
|
416
|
+
*/
|
|
417
|
+
export function numberCharging(obj) {
|
|
418
|
+
const t = obj.time;
|
|
419
|
+
const chargeTime = t.base + Math.trunc((t.dice * (t.sides + 1)) / 2);
|
|
420
|
+
if (chargeTime <= 0)
|
|
421
|
+
return 0;
|
|
422
|
+
if (obj.timeout <= 0)
|
|
423
|
+
return 0;
|
|
424
|
+
const num = Math.trunc((obj.timeout + chargeTime - 1) / chargeTime);
|
|
425
|
+
return Math.min(num, obj.number);
|
|
426
|
+
}
|
|
427
|
+
/** obj_can_zap (obj-util.c L709): any rod in the stack not charging? */
|
|
428
|
+
export function objCanZap(obj) {
|
|
429
|
+
return tvalCanHaveTimeout(obj.tval) && numberCharging(obj) < obj.number;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* object_effect (obj-util.c L886): the effect an object actually runs - the
|
|
433
|
+
* ACTIVATION's effect when it has one, otherwise the kind/instance effect.
|
|
434
|
+
* The activation wins outright, so an artifact or ego activation replaces the
|
|
435
|
+
* base kind's effect rather than being appended to it.
|
|
436
|
+
*/
|
|
437
|
+
export function objectEffect(obj) {
|
|
438
|
+
if (obj.activation)
|
|
439
|
+
return obj.activation.effect;
|
|
440
|
+
return obj.effect;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* obj_is_activatable (obj-util.c L721): a WEARABLE object that has an effect.
|
|
444
|
+
* Note both halves: a non-wearable with an effect (a potion) is not
|
|
445
|
+
* "activatable", and a wearable's effect may come from its kind rather than an
|
|
446
|
+
* activation - the rings of Flames / Acid / Ice / Lightning / Open Wounds /
|
|
447
|
+
* Digging carry an `effect:` in object.txt and no `act:`, so they ARE
|
|
448
|
+
* activatable even though obj.activation is null.
|
|
449
|
+
*/
|
|
450
|
+
export function objIsActivatable(obj) {
|
|
451
|
+
if (!tvalIsWearable(obj.tval))
|
|
452
|
+
return false;
|
|
453
|
+
const effect = objectEffect(obj);
|
|
454
|
+
return effect !== null && effect.length > 0;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* obj_can_activate (obj-util.c L730): activatable AND not recharging. This is
|
|
458
|
+
* NOT obj_can_zap: do_cmd_activate guards on this (cmd-obj.c L886) while
|
|
459
|
+
* do_cmd_zap_rod guards on obj_can_zap (L851), and obj_can_zap requires a ROD
|
|
460
|
+
* tval, so reusing it for activation refuses every artifact and ring.
|
|
461
|
+
*/
|
|
462
|
+
export function objCanActivate(obj) {
|
|
463
|
+
return objIsActivatable(obj) && obj.timeout === 0;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* obj_can_wear (obj-util.c L810): wield_slot(obj) >= 0 - do_cmd_wield's
|
|
467
|
+
* item_tester (cmd-obj.c L284). Over the shipped body plan this is exactly
|
|
468
|
+
* tvalIsWearable (wield_slot handles the same tval set), but it is the slot
|
|
469
|
+
* lookup that decides, so a body plan without some slot type changes the
|
|
470
|
+
* answer. NOTE the upstream wart it inherits: slot_by_type's fallback for
|
|
471
|
+
* "type not on this body" is `false`, i.e. slot 0 - so wield_slot returns 0,
|
|
472
|
+
* not -1, and obj_can_wear stays true for a slot the body does not have.
|
|
473
|
+
*/
|
|
474
|
+
export function objCanWear(state, obj) {
|
|
475
|
+
const player = state.actor.player;
|
|
476
|
+
return wieldSlot(player.body, obj.tval, player.equipment) >= 0;
|
|
477
|
+
}
|
|
478
|
+
/* ------------------------------------------------------------------ *
|
|
479
|
+
* Inscriptions and refuelling (cmd-obj.c, obj-util.c, obj-ignore.c).
|
|
480
|
+
* ------------------------------------------------------------------ */
|
|
481
|
+
/** obj_has_inscrip (obj-util.c L841): does this object carry an inscription? */
|
|
482
|
+
export function objHasInscrip(obj) {
|
|
483
|
+
return !!obj.note;
|
|
484
|
+
}
|
|
485
|
+
/** The equipped light source, or null when no LIGHT slot is worn. */
|
|
486
|
+
function equippedLight(state) {
|
|
487
|
+
const lightSlot = state.actor.player.body.slots.findIndex((s) => s.type === "LIGHT");
|
|
488
|
+
return lightSlot >= 0 ? state.runeEnv.slotObject(lightSlot) : null;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* obj_can_refill (obj-util.c L743): is `obj` a valid fuel source for the
|
|
492
|
+
* currently equipped light - a flask of oil, or another TAKES_FUEL lantern
|
|
493
|
+
* still holding fuel (its timeout)?
|
|
494
|
+
*/
|
|
495
|
+
export function objCanRefill(state, obj) {
|
|
496
|
+
if (obj.flags.has(OF.NO_FUEL))
|
|
497
|
+
return false;
|
|
498
|
+
const light = equippedLight(state);
|
|
499
|
+
if (light && light.flags.has(OF.TAKES_FUEL)) {
|
|
500
|
+
if (tvalIsFuel(obj.tval))
|
|
501
|
+
return true;
|
|
502
|
+
if (tvalIsLight(obj.tval) &&
|
|
503
|
+
obj.flags.has(OF.TAKES_FUEL) &&
|
|
504
|
+
obj.timeout > 0) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* refill_lamp (cmd-obj.c L1008): add `obj`'s fuel (its timeout for a donor
|
|
512
|
+
* lantern, or pval for a flask of oil) to `lamp`, capping at
|
|
513
|
+
* constants.fuelLamp. A stacked donor lantern splits off one empty unit
|
|
514
|
+
* (carried back if there's room, else dropped); a lone donor is emptied in
|
|
515
|
+
* place. A flask is consumed entirely (one unit, from the pack or floor).
|
|
516
|
+
* Recomputes the light radius (PU_TORCH) afterward.
|
|
517
|
+
*/
|
|
518
|
+
export function refillLamp(state, lamp, obj, opts, deps) {
|
|
519
|
+
const env = deps.env ?? {};
|
|
520
|
+
lamp.timeout += obj.timeout ? obj.timeout : obj.pval;
|
|
521
|
+
env.msg?.("You fuel your lamp.");
|
|
522
|
+
if (lamp.timeout >= deps.constants.fuelLamp) {
|
|
523
|
+
lamp.timeout = deps.constants.fuelLamp;
|
|
524
|
+
env.msg?.("Your lamp is full.");
|
|
525
|
+
}
|
|
526
|
+
if (obj.flags.has(OF.TAKES_FUEL)) {
|
|
527
|
+
/* Refilled from a lantern: empty it (splitting one off if stacked). */
|
|
528
|
+
if (obj.number > 1) {
|
|
529
|
+
const used = objectSplit(obj, 1);
|
|
530
|
+
used.timeout = 0;
|
|
531
|
+
const carried = opts.handle !== undefined && !opts.fromFloor;
|
|
532
|
+
if (carried && invenCarryNum(state.gear, used, deps.constants) > 0) {
|
|
533
|
+
invenCarry(state.gear, used, stackLimits(deps.constants));
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
/* Overflow / floor donor: drop_near's own breakage roll (randint0)
|
|
537
|
+
* fires here exactly as upstream, even at chance=0 (a real, faithful
|
|
538
|
+
* RNG draw on this rare branch only - see obj-cmd.test.ts). */
|
|
539
|
+
dropNear(state, used, 0, state.actor.grid, false, true, deps.floorEnv);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
obj.timeout = 0;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
/* Refilled from a flask: consume one unit entirely. */
|
|
548
|
+
if (opts.fromFloor) {
|
|
549
|
+
floorObjectForUse(state, obj, 1);
|
|
550
|
+
}
|
|
551
|
+
else if (opts.handle !== undefined) {
|
|
552
|
+
gearObjectForUse(state.gear, state.actor.player, opts.handle, 1);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
/* PU_TORCH: force the light-radius recalc so a just-refuelled, previously
|
|
556
|
+
* spent (timeout 0) lantern stops reading as dark (player/calcs.ts). */
|
|
557
|
+
state.updateBonuses?.();
|
|
558
|
+
}
|
|
559
|
+
/** Is `obj` presently carried (pack or equipped), by identity? */
|
|
560
|
+
function objIsCarried(state, obj) {
|
|
561
|
+
for (const [handle, stored] of state.gear.store) {
|
|
562
|
+
if (stored !== obj)
|
|
563
|
+
continue;
|
|
564
|
+
return (state.gear.pack.includes(handle) ||
|
|
565
|
+
state.actor.player.equipment.includes(handle));
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* rune_add_autoinscription (obj-ignore.c:172-186): make or extend the rune-`i`
|
|
571
|
+
* autoinscription on one object. No note, or the note already present as a
|
|
572
|
+
* substring, is a no-op; otherwise the note is APPENDED to any existing
|
|
573
|
+
* inscription.
|
|
574
|
+
*
|
|
575
|
+
* Two upstream details preserved:
|
|
576
|
+
* - `strstr(obj->note, rune_note(i))` (obj-ignore.c:176) is a substring test,
|
|
577
|
+
* not equality, so a note already contained in a longer inscription is not
|
|
578
|
+
* appended twice - and an EMPTY note is never appended at all, because
|
|
579
|
+
* strstr(x, "") is non-NULL;
|
|
580
|
+
* - `char current_note[80]` with my_strcpy/my_strcat (obj-ignore.c:174-182)
|
|
581
|
+
* truncates the combined inscription to 79 characters.
|
|
582
|
+
*/
|
|
583
|
+
function runeAddAutoinscription(state, obj, i) {
|
|
584
|
+
const note = state.runeNotes?.get(i);
|
|
585
|
+
if (note === undefined)
|
|
586
|
+
return; // !rune_note(i)
|
|
587
|
+
const current = obj.note ?? "";
|
|
588
|
+
if (obj.note && current.includes(note))
|
|
589
|
+
return;
|
|
590
|
+
obj.note = (current + note).slice(0, 79) || null;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* runes_autoinscribe (obj-ignore.c:217-225): put every applicable rune
|
|
594
|
+
* autoinscription on `obj` - each rune the object carries and the player knows,
|
|
595
|
+
* walked in rune-list order.
|
|
596
|
+
*/
|
|
597
|
+
function runesAutoinscribe(state, obj) {
|
|
598
|
+
if (!state.runeNotes)
|
|
599
|
+
return;
|
|
600
|
+
const env = state.runeEnv;
|
|
601
|
+
const p = state.actor.player;
|
|
602
|
+
const runes = buildRuneList(env);
|
|
603
|
+
for (let i = 0; i < runes.length; i++) {
|
|
604
|
+
const rune = runes[i];
|
|
605
|
+
if (objectHasRune(env, obj, rune) && playerKnowsRune(p, rune)) {
|
|
606
|
+
runeAddAutoinscription(state, obj, i);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* rune_autoinscribe (obj-ignore.c:193-212): the player just set a note on rune
|
|
612
|
+
* `i` - stamp it on every object carrying that rune, on the floor beneath them
|
|
613
|
+
* first and then through the gear. Gated on player_knows_rune (:198).
|
|
614
|
+
* Upstream caller: ui-knowledge.c rune_xtra_act (:2275).
|
|
615
|
+
*/
|
|
616
|
+
export function runeAutoinscribe(state, i) {
|
|
617
|
+
if (!state.runeNotes)
|
|
618
|
+
return;
|
|
619
|
+
const env = state.runeEnv;
|
|
620
|
+
const rune = buildRuneList(env)[i];
|
|
621
|
+
if (!rune)
|
|
622
|
+
return;
|
|
623
|
+
if (!playerKnowsRune(state.actor.player, rune))
|
|
624
|
+
return;
|
|
625
|
+
for (const obj of floorPile(state, state.actor.grid)) {
|
|
626
|
+
if (objectHasRune(env, obj, rune))
|
|
627
|
+
runeAddAutoinscription(state, obj, i);
|
|
628
|
+
}
|
|
629
|
+
for (const obj of state.gear.store.values()) {
|
|
630
|
+
if (objectHasRune(env, obj, rune))
|
|
631
|
+
runeAddAutoinscription(state, obj, i);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* apply_autoinscription (obj-ignore.c L242): put the kind's registered
|
|
636
|
+
* autoinscription on `obj`, unless it is already inscribed, not carried, or
|
|
637
|
+
* ignored. Also clears a stale unaware autoinscription once the kind
|
|
638
|
+
* becomes aware. Returns 1 when an inscription was applied, 0 otherwise
|
|
639
|
+
* (upstream's int return, kept for parity though callers ignore it).
|
|
640
|
+
*/
|
|
641
|
+
export function applyAutoinscription(state, obj, deps) {
|
|
642
|
+
const aware = deps.flavor ? deps.flavor.isAware(obj.kind) : true;
|
|
643
|
+
const note = deps.autoNote?.(obj.kind, aware) ?? null;
|
|
644
|
+
/* Remove an unaware inscription once aware, if it no longer applies. */
|
|
645
|
+
if (aware && obj.note) {
|
|
646
|
+
const unawareNote = deps.autoNote?.(obj.kind, false) ?? null;
|
|
647
|
+
if (unawareNote && obj.note === unawareNote && (!note || obj.note !== note)) {
|
|
648
|
+
obj.note = null;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
/* "Make rune autoinscription go first, for now" (obj-ignore.c:258-259):
|
|
652
|
+
* BEFORE the no-kind-note early return, so the rune notes land even when the
|
|
653
|
+
* kind itself has no autoinscription. */
|
|
654
|
+
runesAutoinscribe(state, obj);
|
|
655
|
+
if (!note)
|
|
656
|
+
return 0;
|
|
657
|
+
if (obj.note)
|
|
658
|
+
return 0;
|
|
659
|
+
if (!objIsCarried(state, obj))
|
|
660
|
+
return 0;
|
|
661
|
+
if (ignoreItemOk(obj, state.ignore, aware))
|
|
662
|
+
return 0;
|
|
663
|
+
obj.note = note.length > 0 ? note : null;
|
|
664
|
+
deps.env?.msg?.(`You autoinscribe ${describeObject(state, obj)}.`);
|
|
665
|
+
return 1;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* autoinscribe_ground (obj-ignore.c:340-348): apply_autoinscription over the
|
|
669
|
+
* whole pile beneath the player.
|
|
670
|
+
*/
|
|
671
|
+
export function autoinscribeGround(state, deps) {
|
|
672
|
+
for (const obj of floorPile(state, state.actor.grid)) {
|
|
673
|
+
applyAutoinscription(state, obj, deps);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* autoinscribe_pack (obj-ignore.c:352-359): apply_autoinscription over p->gear
|
|
678
|
+
* (which upstream is one list covering pack AND equipment, as here).
|
|
679
|
+
*/
|
|
680
|
+
export function autoinscribePack(state, deps) {
|
|
681
|
+
for (const obj of state.gear.store.values()) {
|
|
682
|
+
applyAutoinscription(state, obj, deps);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
/** randcalc(obj->time, 0, RANDOMISE): the recharge time roll. */
|
|
686
|
+
function rollRechargeTime(state, obj) {
|
|
687
|
+
return state.rng.randcalc(obj.time, 0, "randomise");
|
|
688
|
+
}
|
|
689
|
+
/** Build an object's effect chain from its raw records (per use). */
|
|
690
|
+
export function buildObjectEffectChain(records, state, inject = {}) {
|
|
691
|
+
const builder = new EffectBuilder({
|
|
692
|
+
...inject,
|
|
693
|
+
baseValues: {
|
|
694
|
+
PLAYER_LEVEL: () => state.actor.player.lev,
|
|
695
|
+
MAX_SIGHT: () => state.z.maxSight,
|
|
696
|
+
DUNGEON_LEVEL: () => state.chunk.depth,
|
|
697
|
+
/* effects.c L308-315: WEAPON_DAMAGE is a live damroll(dd, ds)+to_d
|
|
698
|
+
* expression base. Keeping this provider lazy preserves the C draw
|
|
699
|
+
* position: the roll occurs exactly when the expression is evaluated. */
|
|
700
|
+
WEAPON_DAMAGE: () => {
|
|
701
|
+
const weapon = state.actor.weapon;
|
|
702
|
+
return weapon
|
|
703
|
+
? state.rng.damroll(weapon.dd, weapon.ds) + weapon.toD
|
|
704
|
+
: 0;
|
|
705
|
+
},
|
|
706
|
+
...inject.baseValues,
|
|
707
|
+
},
|
|
708
|
+
});
|
|
709
|
+
for (const e of records) {
|
|
710
|
+
let spec = e.eff;
|
|
711
|
+
const hasType = e.type !== undefined && e.type !== "";
|
|
712
|
+
if (hasType || e.radius || e.other)
|
|
713
|
+
spec += ":" + (e.type ?? "");
|
|
714
|
+
if (e.radius || e.other)
|
|
715
|
+
spec += ":" + (e.radius ?? 0);
|
|
716
|
+
if (e.other)
|
|
717
|
+
spec += ":" + e.other;
|
|
718
|
+
builder.effect(spec);
|
|
719
|
+
if (e.dice)
|
|
720
|
+
builder.dice(e.dice);
|
|
721
|
+
for (const x of e.expr ?? [])
|
|
722
|
+
builder.expr(x.name, x.base, x.expr);
|
|
723
|
+
}
|
|
724
|
+
return builder.build();
|
|
725
|
+
}
|
|
726
|
+
/** effect_aim over an effect name, from the generated base table. */
|
|
727
|
+
const EFFECT_NEEDS_AIM = new Map(EFFECT_ENTRIES.map((e) => [e.name, e.aim]));
|
|
728
|
+
/** effect_aim over a raw record chain: any effect marked as aimed. */
|
|
729
|
+
export function effectRecordsNeedAim(records) {
|
|
730
|
+
/* RANDOM/SELECT children share the parent walk; the flat list covers them. */
|
|
731
|
+
return records.some((e) => EFFECT_NEEDS_AIM.get(e.eff.split(":")[0] ?? e.eff) === true);
|
|
732
|
+
}
|
|
733
|
+
/** obj_needs_aim (obj-util.c L899), on the raw effect records. */
|
|
734
|
+
export function objNeedsAim(obj, deps) {
|
|
735
|
+
const aimed = effectRecordsNeedAim(obj.effect ?? []);
|
|
736
|
+
const aware = deps.flavor ? deps.flavor.isAware(obj.kind) : true;
|
|
737
|
+
return aimed || tvalIsWand(obj.tval) || (tvalIsRod(obj.tval) && !aware);
|
|
738
|
+
}
|
|
739
|
+
/** player_is_shapechanged (player-util.c L1065): null shape = normal. */
|
|
740
|
+
export function playerIsShapechanged(state) {
|
|
741
|
+
return state.actor.player.shape !== null;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* player_resume_normal_shape (player-util.c L1048): back to normal form,
|
|
745
|
+
* killing the vampire attack and refreshing the bonuses.
|
|
746
|
+
*/
|
|
747
|
+
export function playerResumeNormalShape(state, env = {}) {
|
|
748
|
+
state.actor.player.shape = null;
|
|
749
|
+
env.msg?.("You resume your usual shape.");
|
|
750
|
+
/* Kill vampire attack. */
|
|
751
|
+
state.actor.player.timed[TMD.ATT_VAMP] = 0;
|
|
752
|
+
state.updateBonuses?.();
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* player_get_resume_normal_shape (player-util.c L1022): a shapechanged
|
|
756
|
+
* player must return to normal form before acting with hands/voice. The
|
|
757
|
+
* y/n/r prompt is the confirm seam (headless default: change back and
|
|
758
|
+
* proceed).
|
|
759
|
+
*/
|
|
760
|
+
export function playerGetResumeNormalShape(state, env = {}) {
|
|
761
|
+
if (!playerIsShapechanged(state))
|
|
762
|
+
return true;
|
|
763
|
+
env.msg?.(`You cannot do this while in ${state.actor.player.shape.name} form.`);
|
|
764
|
+
if (env.confirm?.("Change back and continue? ") ?? true) {
|
|
765
|
+
playerResumeNormalShape(state, env);
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
768
|
+
return false;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* player_can_read (player-util.c L1166): scrolls and spellbooks need working
|
|
772
|
+
* eyes, light, a clear head and intact memory. Checked in this exact order, and
|
|
773
|
+
* each refusal prints its own message and spends no turn. do_cmd_read_scroll
|
|
774
|
+
* (cmd-obj.c L748) calls this with show_msg true BEFORE cmd_get_item, so a blind
|
|
775
|
+
* player with no scrolls at all still hears "You can't see anything." rather
|
|
776
|
+
* than the "You have no scrolls to read." rejection.
|
|
777
|
+
*
|
|
778
|
+
* Reached from two places upstream and both are this same predicate:
|
|
779
|
+
* do_cmd_read_scroll (cmd-obj.c:748) and the 'r' key's prereq
|
|
780
|
+
* player_can_read_prereq (player-util.c:1264, wired at ui-game.c:131) - which
|
|
781
|
+
* is why the show_msg parameter exists rather than the messages being inlined.
|
|
782
|
+
* The prereq's TMD_COMMAND bypass is NOT reproduced here: while TMD_COMMAND runs
|
|
783
|
+
* the turn loop redirects every command to do_cmd_mon_command before the handler
|
|
784
|
+
* is reached (game/player-turn.ts L708-714), which is exactly what the bypass
|
|
785
|
+
* exists to permit.
|
|
786
|
+
*
|
|
787
|
+
* Note the order and strings differ from player_can_cast (L1087), which folds
|
|
788
|
+
* blind and no_light into one "You cannot see!" and has no amnesia check.
|
|
789
|
+
*/
|
|
790
|
+
export function playerCanRead(state, env = {}, showMsg = true) {
|
|
791
|
+
const p = state.actor.player;
|
|
792
|
+
if ((p.timed[TMD.BLIND] ?? 0) > 0) {
|
|
793
|
+
if (showMsg)
|
|
794
|
+
env.msg?.("You can't see anything.");
|
|
795
|
+
return false;
|
|
796
|
+
}
|
|
797
|
+
if (noLight(state)) {
|
|
798
|
+
if (showMsg)
|
|
799
|
+
env.msg?.("You have no light to read by.");
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
if ((p.timed[TMD.CONFUSED] ?? 0) > 0) {
|
|
803
|
+
if (showMsg)
|
|
804
|
+
env.msg?.("You are too confused to read!");
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
if ((p.timed[TMD.AMNESIA] ?? 0) > 0) {
|
|
808
|
+
if (showMsg)
|
|
809
|
+
env.msg?.("You can't remember how to read!");
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
return true;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* no_light (cave-view.c L913): the player's own grid is not currently seen.
|
|
816
|
+
* Shared by playerCanRead here and player_can_cast (game/spell-cmd.ts).
|
|
817
|
+
*
|
|
818
|
+
* SQUARE_SEEN is maintained by update_view, which this port drives through the
|
|
819
|
+
* `state.updateFov` host seam. This used to open with a guard - `if
|
|
820
|
+
* (state.updateFov === undefined) return false` - described in its own comment as
|
|
821
|
+
* "a seam guard, not a rule of the game", because a host that installed no seam
|
|
822
|
+
* left SEEN clear on every grid and would have found casting and reading
|
|
823
|
+
* permanently impossible.
|
|
824
|
+
*
|
|
825
|
+
* The guard is gone because its premise is: core installs a DEFAULT updateFov in
|
|
826
|
+
* wireGame, so startGame and loadGame both maintain SEEN with no host cooperation
|
|
827
|
+
* and there is no configuration left in which the flag carries no information.
|
|
828
|
+
* Keeping it would mean a host that deleted the seam silently got non-upstream
|
|
829
|
+
* spell rules - the guard's whole purpose was to make an unplayable state
|
|
830
|
+
* playable, and that state cannot happen now.
|
|
831
|
+
*
|
|
832
|
+
* So this is upstream verbatim for every caller.
|
|
833
|
+
*/
|
|
834
|
+
export function noLight(state) {
|
|
835
|
+
return !squareIsSeen(state.chunk, state.actor.grid);
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* player_confuse_dir (player-util.c): confusion randomises the direction
|
|
839
|
+
* 75% of the time (always for "no direction").
|
|
840
|
+
*/
|
|
841
|
+
export function playerConfuseDir(state, dir, too = false) {
|
|
842
|
+
if ((state.actor.player.timed[TMD.CONFUSED] ?? 0) > 0) {
|
|
843
|
+
let newDir = dir;
|
|
844
|
+
if (dir === 5 || state.rng.randint0(100) < 75) {
|
|
845
|
+
/* Random direction. */
|
|
846
|
+
newDir = DDD[state.rng.randint0(8)];
|
|
847
|
+
}
|
|
848
|
+
/* player-util.c L1363-1366: running is refused after the same confusion
|
|
849
|
+
* roll, with the C's message. */
|
|
850
|
+
if (too) {
|
|
851
|
+
state.msg?.("You are too confused.");
|
|
852
|
+
return dir;
|
|
853
|
+
}
|
|
854
|
+
/* player-util.c L1369: emit "You are confused." and report the change only
|
|
855
|
+
* when the direction actually changed (a same-direction roll is silent).
|
|
856
|
+
* The RNG draw above is unconditional whenever confused, matching C. */
|
|
857
|
+
if (newDir !== dir) {
|
|
858
|
+
state.msg?.("You are confused.");
|
|
859
|
+
return newDir;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return dir;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* object_learn_on_use (obj-knowledge.c L1925-1936), XP slice (gap 4.3): the
|
|
866
|
+
* flavor-awareness half is handled by the caller (objectFlavorAware); this adds
|
|
867
|
+
* the experience reward player_exp_gain(p, (lev + p->lev/2)/p->lev) with lev the
|
|
868
|
+
* used object's KIND level. Integer division throughout, exactly as upstream.
|
|
869
|
+
*/
|
|
870
|
+
function objectLearnOnUseXp(state, obj, deps) {
|
|
871
|
+
if (!deps.expGain)
|
|
872
|
+
return;
|
|
873
|
+
const p = state.actor.player;
|
|
874
|
+
const lev = obj.kind.level;
|
|
875
|
+
deps.expGain(Math.trunc((lev + Math.trunc(p.lev / 2)) / p.lev));
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* activation_message (cmd-obj.c L127): print an activated object's custom
|
|
879
|
+
* message. The message text comes from the activation (activation.txt msg:),
|
|
880
|
+
* but an artifact carrying its own alt_msg (artifact.txt msg:) overrides it -
|
|
881
|
+
* and the override only fires when the activation itself defines a message. The
|
|
882
|
+
* text is run through print_custom_message's {name}/{kind}/{s}/{is} object-tag
|
|
883
|
+
* substitution (obj-util.c L1118): {name} -> object_desc(PREFIX|BASE), {kind} ->
|
|
884
|
+
* object_kind_name (easy_know), {s}/{is} keyed on the stack count.
|
|
885
|
+
*/
|
|
886
|
+
function activationMessage(state, obj, env) {
|
|
887
|
+
if (!obj.activation?.message)
|
|
888
|
+
return;
|
|
889
|
+
const message = obj.artifact && obj.artifact.altMsg
|
|
890
|
+
? obj.artifact.altMsg
|
|
891
|
+
: obj.activation.message;
|
|
892
|
+
const text = substituteTimedMessage(message, {
|
|
893
|
+
name: describeObject(state, obj, ODESC.PREFIX | ODESC.BASE),
|
|
894
|
+
kind: objDescNameFormat(obj.kind.name, null, false),
|
|
895
|
+
number: obj.number,
|
|
896
|
+
});
|
|
897
|
+
env.msg?.(text);
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* use_aux (cmd-obj.c L407): use an object the right way - aim resolution,
|
|
901
|
+
* the device check, charge/timeout/single-use deduction with restore on an
|
|
902
|
+
* unused effect, and the effect chain run with a player source.
|
|
903
|
+
*/
|
|
904
|
+
export function useAux(state, obj, use, deps, opts = {}) {
|
|
905
|
+
const env = deps.env ?? {};
|
|
906
|
+
const fromFloor = opts.fromFloor ?? false;
|
|
907
|
+
const wasAware = deps.flavor ? deps.flavor.isAware(obj.kind) : true;
|
|
908
|
+
/* Determine whether we know an item needs to be aimed. */
|
|
909
|
+
const knownAim = tvalIsWand(obj.tval) || tvalIsRod(obj.tval) || wasAware;
|
|
910
|
+
let dir = 5;
|
|
911
|
+
if (objNeedsAim(obj, deps)) {
|
|
912
|
+
if (!knownAim) {
|
|
913
|
+
/* Unknown things with no obvious aim get a random direction. */
|
|
914
|
+
dir = DDD[state.rng.randint0(8)];
|
|
915
|
+
}
|
|
916
|
+
else {
|
|
917
|
+
dir = opts.dir ?? env.chooseDir?.() ?? 5;
|
|
918
|
+
}
|
|
919
|
+
/* Confusion wrecks aim. */
|
|
920
|
+
dir = playerConfuseDir(state, dir);
|
|
921
|
+
}
|
|
922
|
+
/* Check for use if necessary. */
|
|
923
|
+
let canUse = 1;
|
|
924
|
+
if (use === USE.CHARGE || use === USE.TIMEOUT) {
|
|
925
|
+
canUse = checkDevices(state, obj, env);
|
|
926
|
+
}
|
|
927
|
+
if (canUse > 0) {
|
|
928
|
+
const beam = beamChance(obj.tval);
|
|
929
|
+
const level = objectLevel(obj);
|
|
930
|
+
const boost = Math.max(Math.trunc(((state.actor.combat.skills[SKILL.DEVICE] ?? 0) - level) / 2), 0);
|
|
931
|
+
/* Sound / message (cmd-obj.c L493-504): an activation prints the generic
|
|
932
|
+
* "You activate it." then its own activation_message; otherwise the kind's
|
|
933
|
+
* effect_msg (always) or vis_msg (only when not blind). */
|
|
934
|
+
if (obj.activation) {
|
|
935
|
+
env.msg?.("You activate it.");
|
|
936
|
+
activationMessage(state, obj, env);
|
|
937
|
+
}
|
|
938
|
+
else if (obj.kind.effectMsg) {
|
|
939
|
+
env.msg?.(obj.kind.effectMsg);
|
|
940
|
+
}
|
|
941
|
+
else if (obj.kind.visMsg &&
|
|
942
|
+
(state.actor.player.timed[TMD.BLIND] ?? 0) === 0) {
|
|
943
|
+
env.msg?.(obj.kind.visMsg);
|
|
944
|
+
}
|
|
945
|
+
/* Capture the describe inputs before the effect can rearrange the pack
|
|
946
|
+
* (cmd-obj.c L462-483): the gear label of the item and the count to report.
|
|
947
|
+
* For anything but a CHARGE / TIMEOUT device that count is the AGGREGATE
|
|
948
|
+
* across every like stack (object_pack_total, L474), and the label becomes
|
|
949
|
+
* the first such stack's - "You have 3 Scrolls of Light (1st d)." A charge
|
|
950
|
+
* or recharging notice is stack-specific, so those keep their own number
|
|
951
|
+
* (L480). A floor object has no pack context at all (L465). */
|
|
952
|
+
let describeLabel = opts.handle !== undefined ? gearLabelFor(state, opts.handle) : "";
|
|
953
|
+
let startNumber = obj.number;
|
|
954
|
+
let firstRemainder = null;
|
|
955
|
+
if (!fromFloor && use !== USE.CHARGE && use !== USE.TIMEOUT) {
|
|
956
|
+
const view = packTotalView(state.gear);
|
|
957
|
+
const agg = objectPackTotal(view, obj, false);
|
|
958
|
+
startNumber = agg.total;
|
|
959
|
+
firstRemainder = agg.first;
|
|
960
|
+
/* One stack only: nothing to call "1st" (L477-479). */
|
|
961
|
+
if (firstRemainder && firstRemainder.number === agg.total) {
|
|
962
|
+
firstRemainder = null;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
/* Tentatively deduct floor-object usage before the effect (the effect
|
|
966
|
+
* could leave the object inaccessible). */
|
|
967
|
+
let deductBefore = false;
|
|
968
|
+
let charges = 0;
|
|
969
|
+
let singleUsed = null;
|
|
970
|
+
if (fromFloor) {
|
|
971
|
+
if (use === USE.SINGLE) {
|
|
972
|
+
deductBefore = true;
|
|
973
|
+
singleUsed = floorObjectForUse(state, obj, 1).usable;
|
|
974
|
+
}
|
|
975
|
+
else if (use === USE.CHARGE) {
|
|
976
|
+
deductBefore = true;
|
|
977
|
+
charges = obj.pval;
|
|
978
|
+
obj.pval--;
|
|
979
|
+
}
|
|
980
|
+
else if (use === USE.TIMEOUT) {
|
|
981
|
+
deductBefore = true;
|
|
982
|
+
charges = obj.timeout;
|
|
983
|
+
obj.timeout += rollRechargeTime(state, obj);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
/* Do effect. use_aux takes its chain from object_effect(obj) (cmd-obj.c
|
|
987
|
+
* L410 `struct effect *effect = object_effect(obj);`), so an activation's
|
|
988
|
+
* effect REPLACES the base kind's - reading obj.effect here ran a
|
|
989
|
+
* Narthanc-style artifact's (empty) kind effect instead of its activation. */
|
|
990
|
+
const chain = buildObjectEffectChain(objectEffect(obj) ?? [], state, deps.inject);
|
|
991
|
+
const ctx = attachGameEnv(buildEffectContext(state, deps.envDeps), {
|
|
992
|
+
state,
|
|
993
|
+
cast: deps.cast,
|
|
994
|
+
/* take_hit consequences for effects that rebound damage onto the player
|
|
995
|
+
* (EF_BANISH), so such a death records died_from too. */
|
|
996
|
+
...(deps.envDeps.takeHitHooks
|
|
997
|
+
? { takeHitHooks: deps.envDeps.takeHitHooks }
|
|
998
|
+
: {}),
|
|
999
|
+
/* target_get inside the handlers: a DIR_TARGET cast re-reads the
|
|
1000
|
+
* live target per handler, as upstream. */
|
|
1001
|
+
get aimed() {
|
|
1002
|
+
return targetOkay(state) ? targetGet(state) : undefined;
|
|
1003
|
+
},
|
|
1004
|
+
...(deps.teleport ? { teleport: deps.teleport } : {}),
|
|
1005
|
+
...(deps.general ? { general: deps.general } : {}),
|
|
1006
|
+
...(deps.item ? { item: deps.item } : {}),
|
|
1007
|
+
...(deps.summon ? { summon: deps.summon } : {}),
|
|
1008
|
+
/* Flavor knowledge for item-identifying effects (EF_IDENTIFY fires the
|
|
1009
|
+
* object_flavor_aware side effect of player_know_object). */
|
|
1010
|
+
...(deps.flavor ? { flavor: deps.flavor } : {}),
|
|
1011
|
+
...(deps.flavorDeps ? { flavorDeps: deps.flavorDeps } : {}),
|
|
1012
|
+
});
|
|
1013
|
+
const ident = { value: false };
|
|
1014
|
+
targetFix(state);
|
|
1015
|
+
/* cmd_get_item "tgtitem" / "tgtcurse" presets: the item-choosing effects
|
|
1016
|
+
* read state.itemTarget / state.curseTarget through the getItem seam. Set
|
|
1017
|
+
* before the run, cleared after (cmd_set_arg_item's scope). */
|
|
1018
|
+
state.itemRequest = null;
|
|
1019
|
+
state.itemTarget = opts.tgtItem ?? null;
|
|
1020
|
+
state.curseTarget = opts.tgtCurse ?? null;
|
|
1021
|
+
const used = deps.registry.effectDo(chain, ctx, {
|
|
1022
|
+
origin: sourcePlayer(),
|
|
1023
|
+
obj,
|
|
1024
|
+
ident,
|
|
1025
|
+
aware: wasAware,
|
|
1026
|
+
dir,
|
|
1027
|
+
beam,
|
|
1028
|
+
boost,
|
|
1029
|
+
});
|
|
1030
|
+
state.itemTarget = null;
|
|
1031
|
+
state.curseTarget = null;
|
|
1032
|
+
targetRelease(state);
|
|
1033
|
+
if (!used && deductBefore) {
|
|
1034
|
+
/* Restore the tentative deduction. */
|
|
1035
|
+
if (use === USE.SINGLE && singleUsed) {
|
|
1036
|
+
dropNear(state, singleUsed, 0, state.actor.grid, false, true, deps.floorEnv);
|
|
1037
|
+
}
|
|
1038
|
+
else if (use === USE.CHARGE) {
|
|
1039
|
+
obj.pval = charges;
|
|
1040
|
+
}
|
|
1041
|
+
else if (use === USE.TIMEOUT) {
|
|
1042
|
+
obj.timeout = charges;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
/* Increase knowledge. */
|
|
1046
|
+
if (deps.flavor) {
|
|
1047
|
+
const knowObj = singleUsed ?? obj;
|
|
1048
|
+
const flavorDeps = deps.flavorDeps ?? NOOP_FLAVOR_AWARE_DEPS;
|
|
1049
|
+
if (use === USE.SINGLE) {
|
|
1050
|
+
/* Single use items are automatically learned. */
|
|
1051
|
+
if (!wasAware) {
|
|
1052
|
+
deps.flavor.objectFlavorAware(knowObj.kind, flavorDeps);
|
|
1053
|
+
objectLearnOnUseXp(state, knowObj, deps);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
else if (!wasAware && ident.value) {
|
|
1057
|
+
deps.flavor.objectFlavorAware(knowObj.kind, flavorDeps);
|
|
1058
|
+
objectLearnOnUseXp(state, knowObj, deps);
|
|
1059
|
+
}
|
|
1060
|
+
else {
|
|
1061
|
+
deps.flavor.setTried(knowObj.kind);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
/* Use up, deduct charge, or apply timeout if it wasn't done before. */
|
|
1065
|
+
if (used && !deductBefore) {
|
|
1066
|
+
if (use === USE.CHARGE) {
|
|
1067
|
+
obj.pval--;
|
|
1068
|
+
}
|
|
1069
|
+
else if (use === USE.TIMEOUT) {
|
|
1070
|
+
obj.timeout += rollRechargeTime(state, obj);
|
|
1071
|
+
}
|
|
1072
|
+
else if (use === USE.SINGLE && opts.handle !== undefined) {
|
|
1073
|
+
gearObjectForUse(state.gear, state.actor.player, opts.handle, 1);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
/* Describe what's left (cmd-obj.c L633-706). Single-use items are always
|
|
1077
|
+
* described; a charge/timeout device only when it was just identified (and
|
|
1078
|
+
* never for wearables, which take the update-knowledge branch). Otherwise a
|
|
1079
|
+
* used charge device reports its remaining charges. */
|
|
1080
|
+
const describe = use === USE.SINGLE ||
|
|
1081
|
+
(!tvalIsWearable(obj.tval) && !wasAware && ident.value);
|
|
1082
|
+
if (describe) {
|
|
1083
|
+
const shown = startNumber - (used && use === USE.SINGLE ? 1 : 0);
|
|
1084
|
+
const name = describeObject(state, obj, ODESC.PREFIX | ODESC.FULL | ODESC.ALTNUM, shown);
|
|
1085
|
+
if (fromFloor)
|
|
1086
|
+
env.msg?.(`You see ${name}.`);
|
|
1087
|
+
else {
|
|
1088
|
+
/* cmd-obj.c L692-698: the "1st" label is looked up AFTER the effect,
|
|
1089
|
+
* because the pack may have moved underneath it. */
|
|
1090
|
+
if (firstRemainder)
|
|
1091
|
+
describeLabel = packLabelFor(state, firstRemainder);
|
|
1092
|
+
env.msg?.(firstRemainder
|
|
1093
|
+
? `You have ${name} (1st ${describeLabel}).`
|
|
1094
|
+
: `You have ${name} (${describeLabel}).`);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
else if (used &&
|
|
1098
|
+
use === USE.CHARGE &&
|
|
1099
|
+
tvalCanHaveCharges(obj.tval) &&
|
|
1100
|
+
(deps.flavor ? deps.flavor.isAware(obj.kind) : true)) {
|
|
1101
|
+
/* inven_item_charges / floor_item_charges (obj-gear.c L790-799). */
|
|
1102
|
+
env.msg?.(`You have ${obj.pval} charge${obj.pval === 1 ? "" : "s"} remaining.`);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
/* Use the turn (even a device fizzle spends it, as upstream). */
|
|
1106
|
+
return { turnSpent: true, used: canUse > 0 };
|
|
1107
|
+
}
|
|
1108
|
+
/* ------------------------------------------------------------------ *
|
|
1109
|
+
* Command actions.
|
|
1110
|
+
* ------------------------------------------------------------------ */
|
|
1111
|
+
/** Resolve a command's object: a gear handle or a floor pile position. */
|
|
1112
|
+
function commandObject(state, cmd) {
|
|
1113
|
+
const args = cmd.args ?? {};
|
|
1114
|
+
const handle = typeof args["handle"] === "number" ? args["handle"] : null;
|
|
1115
|
+
if (handle !== null) {
|
|
1116
|
+
const obj = gearGet(state.gear, handle);
|
|
1117
|
+
return obj ? { obj, handle, fromFloor: false } : null;
|
|
1118
|
+
}
|
|
1119
|
+
const floorIdx = typeof args["floor"] === "number" ? args["floor"] : null;
|
|
1120
|
+
if (floorIdx !== null) {
|
|
1121
|
+
const pile = floorPile(state, state.actor.grid);
|
|
1122
|
+
const obj = pile[floorIdx];
|
|
1123
|
+
return obj ? { obj, fromFloor: true } : null;
|
|
1124
|
+
}
|
|
1125
|
+
return null;
|
|
1126
|
+
}
|
|
1127
|
+
function commandDir(cmd) {
|
|
1128
|
+
const d = cmd.args?.["dir"] ?? cmd.dir;
|
|
1129
|
+
return typeof d === "number" ? d : undefined;
|
|
1130
|
+
}
|
|
1131
|
+
/** cmd_get_arg_item "tgtitem": the shell's pre-resolved item-effect target. */
|
|
1132
|
+
function commandTargetItem(cmd) {
|
|
1133
|
+
const t = cmd.args?.["tgtitem"];
|
|
1134
|
+
if (t && typeof t === "object") {
|
|
1135
|
+
if (typeof t.handle === "number") {
|
|
1136
|
+
return { handle: t.handle };
|
|
1137
|
+
}
|
|
1138
|
+
if (typeof t.floor === "number") {
|
|
1139
|
+
return { floor: t.floor };
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return undefined;
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* A use command over a tval filter and use kind.
|
|
1146
|
+
*
|
|
1147
|
+
* `ready` is the command's OWN pre-use guard, because upstream does NOT share
|
|
1148
|
+
* one: do_cmd_zap_rod tests obj_can_zap and says "That rod is still charging."
|
|
1149
|
+
* (cmd-obj.c L851-855) while do_cmd_activate tests obj_can_activate and says
|
|
1150
|
+
* "That item is still charging." (L886-890). obj_can_zap requires a rod tval,
|
|
1151
|
+
* so the two are not interchangeable - using obj_can_zap for activation
|
|
1152
|
+
* refused EVERY artifact and ring.
|
|
1153
|
+
*/
|
|
1154
|
+
function useCommand(deps, filter, use, ready) {
|
|
1155
|
+
return (state, cmd) => {
|
|
1156
|
+
const found = commandObject(state, cmd);
|
|
1157
|
+
if (!found || !filter(found.obj))
|
|
1158
|
+
return 0;
|
|
1159
|
+
if (ready && !ready.ok(found.obj)) {
|
|
1160
|
+
deps.env?.msg?.(ready.msg);
|
|
1161
|
+
return 0;
|
|
1162
|
+
}
|
|
1163
|
+
if (use === USE.CHARGE && found.obj.pval <= 0) {
|
|
1164
|
+
/* do_cmd_aim_wand (cmd-obj.c L817-820) / do_cmd_use_staff (L783-786)
|
|
1165
|
+
* pre-check obj_has_charges and return BEFORE use_aux, so an empty
|
|
1166
|
+
* device costs no turn (checkDevices' "... no charges left." path in
|
|
1167
|
+
* useAux would otherwise burn one). */
|
|
1168
|
+
deps.env?.msg?.(tvalIsWand(found.obj.tval)
|
|
1169
|
+
? "That wand has no charges."
|
|
1170
|
+
: "That staff has no charges.");
|
|
1171
|
+
return 0;
|
|
1172
|
+
}
|
|
1173
|
+
const dir = commandDir(cmd);
|
|
1174
|
+
const tgtItem = commandTargetItem(cmd);
|
|
1175
|
+
const tgtCurse = cmd.args?.["tgtcurse"];
|
|
1176
|
+
const result = useAux(state, found.obj, use, deps, {
|
|
1177
|
+
fromFloor: found.fromFloor,
|
|
1178
|
+
...(found.handle !== undefined ? { handle: found.handle } : {}),
|
|
1179
|
+
...(dir !== undefined ? { dir } : {}),
|
|
1180
|
+
...(tgtItem ? { tgtItem } : {}),
|
|
1181
|
+
...(typeof tgtCurse === "number" ? { tgtCurse } : {}),
|
|
1182
|
+
});
|
|
1183
|
+
/* "Autoinscribe if we are guaranteed to still have any"
|
|
1184
|
+
* (cmd-obj.c:717-719): `if (!none_left && !from_floor)`. none_left is
|
|
1185
|
+
* gear_object_for_use consuming the last of the stack, which here is the
|
|
1186
|
+
* gear handle no longer resolving. */
|
|
1187
|
+
if (!found.fromFloor && found.handle !== undefined) {
|
|
1188
|
+
const left = state.gear.store.get(found.handle);
|
|
1189
|
+
if (left)
|
|
1190
|
+
applyAutoinscription(state, left, deps);
|
|
1191
|
+
}
|
|
1192
|
+
return result.turnSpent ? state.z.moveEnergy : 0;
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Register the object commands (wield / takeoff / drop / eat / quaff /
|
|
1197
|
+
* read / use-staff / aim-wand / zap-rod / activate) on the registry.
|
|
1198
|
+
*/
|
|
1199
|
+
export function installObjCommands(registry, deps) {
|
|
1200
|
+
/* player_get_resume_normal_shape gates the hands/voice commands
|
|
1201
|
+
* (cmd-obj.c: takeoff/wield/drop, scroll/staff/wand/rod/activate AND
|
|
1202
|
+
* quaff - do_cmd_quaff_potion opens with the resume gate at cmd-obj.c L923).
|
|
1203
|
+
* do_cmd_eat_food (L899) is the one use command with NO gate, so eating stays
|
|
1204
|
+
* possible in any shape. */
|
|
1205
|
+
const gated = (fn) => {
|
|
1206
|
+
return (state, cmd) => playerGetResumeNormalShape(state, deps.env ?? {}) ? fn(state, cmd) : 0;
|
|
1207
|
+
};
|
|
1208
|
+
/* do_cmd_wield (cmd-obj.c:265-353): wear/wield from the pack or the floor.
|
|
1209
|
+
*
|
|
1210
|
+
* The statement order below is upstream's, and it is load-bearing:
|
|
1211
|
+
* 1. cmd_get_item for the item
|
|
1212
|
+
* 2. slot = wield_slot(obj); equip_obj = slot_object(player, slot)
|
|
1213
|
+
* 3. slot empty -> inven_wield and return, asking nothing
|
|
1214
|
+
* 4. ring -> the SECOND cmd_get_item, "Replace which ring? ", which
|
|
1215
|
+
* overwrites slot with the hand the player chose
|
|
1216
|
+
* 5. obj_can_takeoff refusal (sticky)
|
|
1217
|
+
* 6. the "!t" get_check loop
|
|
1218
|
+
* 7. act wording from the SLOT's type, then inven_wield(obj, slot)
|
|
1219
|
+
* 8. the MSG_WIELD "You were ..." line
|
|
1220
|
+
*
|
|
1221
|
+
* The floor pickup belongs at step 7, not step 1: upstream carries a floor
|
|
1222
|
+
* item INSIDE inven_wield (`floor_object_for_use` + `inven_carry`,
|
|
1223
|
+
* obj-gear.c:973-976), which is past every abort above. Doing it first - as the
|
|
1224
|
+
* port did - leaked the item into the pack when the player escaped the ring or
|
|
1225
|
+
* "!t" prompt, or when the slot turned out to be stuck. */
|
|
1226
|
+
registry.register("wield", gated((state, cmd) => {
|
|
1227
|
+
const found = commandObject(state, cmd);
|
|
1228
|
+
if (!found)
|
|
1229
|
+
return 0;
|
|
1230
|
+
const player = state.actor.player;
|
|
1231
|
+
/* Step 2. */
|
|
1232
|
+
let targetSlot = wieldSlot(player.body, found.obj.tval, player.equipment);
|
|
1233
|
+
if (targetSlot < 0 || targetSlot >= player.body.count)
|
|
1234
|
+
return 0;
|
|
1235
|
+
/* Step 4: the ring question. The core command path cannot block on UI, so
|
|
1236
|
+
* the shell resolves wieldRingChoice() and passes the chosen slot back as
|
|
1237
|
+
* the "slot" argument, which is precisely what upstream's cmd_get_item does
|
|
1238
|
+
* when the command already carries the answer (cmd-obj.c:298). With no
|
|
1239
|
+
* answer supplied (a headless driver, the borg) the pre-prompt wield_slot
|
|
1240
|
+
* stands, the same "unprompted terminal takes the default" rule the confirm
|
|
1241
|
+
* seam uses. */
|
|
1242
|
+
if ((player.equipment[targetSlot] ?? 0) !== 0 && tvalIsRing(found.obj.tval)) {
|
|
1243
|
+
const chosen = cmd.args?.["slot"];
|
|
1244
|
+
if (typeof chosen === "number") {
|
|
1245
|
+
const chosenHandle = player.equipment[chosen] ?? 0;
|
|
1246
|
+
const chosenObj = chosenHandle ? gearGet(state.gear, chosenHandle) : null;
|
|
1247
|
+
/* Only a worn RING is a legal answer (the tval_is_ring filter on
|
|
1248
|
+
* USE_EQUIP); anything else is not something cmd_get_item could have
|
|
1249
|
+
* returned, so it is ignored rather than obeyed. */
|
|
1250
|
+
if (chosenObj && tvalIsRing(chosenObj.tval))
|
|
1251
|
+
targetSlot = chosen;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
const displacedHandle = player.equipment[targetSlot] ?? 0;
|
|
1255
|
+
const displaced = displacedHandle ? gearGet(state.gear, displacedHandle) : null;
|
|
1256
|
+
/* Step 5: prevent wielding into a stickied slot (cmd-obj.c:313-320).
|
|
1257
|
+
* obj_can_takeoff is !OF_STICKY (obj-util.c L794), and the refusal names the
|
|
1258
|
+
* stuck item by its base description plus equip_describe's wording for the
|
|
1259
|
+
* slot. Draws no RNG and spends no energy: the command aborts before
|
|
1260
|
+
* inven_wield. */
|
|
1261
|
+
if (displaced && displaced.flags.has(OF.STICKY)) {
|
|
1262
|
+
deps.env?.msg?.(`You cannot remove the ${describeObject(state, displaced, ODESC.BASE)} ` +
|
|
1263
|
+
`you are ${equipDescribe(state, targetSlot)}.`);
|
|
1264
|
+
return 0;
|
|
1265
|
+
}
|
|
1266
|
+
/* Step 6: the "!t" checks for taking off (cmd-obj.c:321-330). One refusal
|
|
1267
|
+
* ends the command with no turn spent. The shell has normally answered these
|
|
1268
|
+
* already (it must, to ask before the item moves); the seam is here too so a
|
|
1269
|
+
* driver that queues the command directly still honours the inscription. */
|
|
1270
|
+
const ask = wieldTakeoffConfirm(state, targetSlot);
|
|
1271
|
+
if (ask) {
|
|
1272
|
+
for (let i = 0; i < ask.count; i++) {
|
|
1273
|
+
if (!(deps.env?.confirm?.(ask.prompt) ?? true))
|
|
1274
|
+
return 0;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
/* Step 7: the wording comes from the SLOT's type upstream
|
|
1278
|
+
* (slot_type_is(player, slot, EQUIP_WEAPON), cmd-obj.c:337-347), not from the
|
|
1279
|
+
* displaced item's tval - and it is read BEFORE inven_wield empties the
|
|
1280
|
+
* slot. */
|
|
1281
|
+
const slotType = player.body.slots[targetSlot]?.type ?? "";
|
|
1282
|
+
const act = slotType === "WEAPON"
|
|
1283
|
+
? "You were wielding"
|
|
1284
|
+
: slotType === "BOW" || slotType === "LIGHT"
|
|
1285
|
+
? "You were holding"
|
|
1286
|
+
: "You were wearing";
|
|
1287
|
+
/* inven_wield's own floor path (obj-gear.c:973-976), reached only now. */
|
|
1288
|
+
let handle = found.handle;
|
|
1289
|
+
if (found.fromFloor) {
|
|
1290
|
+
const { usable } = floorObjectForUse(state, found.obj, 1);
|
|
1291
|
+
handle = invenCarry(state.gear, usable, stackLimits(deps.constants));
|
|
1292
|
+
}
|
|
1293
|
+
if (handle === undefined)
|
|
1294
|
+
return 0;
|
|
1295
|
+
/* invenWield owns the MSG_WIELD line, the sticky warning, combine_pack and
|
|
1296
|
+
* pack_overflow, in that upstream order (obj-gear.c L986-1010). The slot is
|
|
1297
|
+
* passed, not re-derived: for a ring it is the hand the player chose. */
|
|
1298
|
+
const slot = invenWield(state, handle, deps.constants, packOpts(state, deps), targetSlot);
|
|
1299
|
+
if (slot < 0)
|
|
1300
|
+
return 0;
|
|
1301
|
+
/* Step 8. The displaced item is now back in the pack - or on the floor if
|
|
1302
|
+
* pack_overflow shed it, in which case gear_to_label gives '\0' and the
|
|
1303
|
+
* port's gearLabelFor gives "" (cmd-obj.c L337-354, read AFTER
|
|
1304
|
+
* combine_pack, so the label is the post-combine one). */
|
|
1305
|
+
if (displaced) {
|
|
1306
|
+
const dname = describeObject(state, displaced);
|
|
1307
|
+
const dlabel = gearLabelFor(state, displacedHandle);
|
|
1308
|
+
deps.env?.msg?.(`${act} ${dname} (${dlabel}).`);
|
|
1309
|
+
}
|
|
1310
|
+
return state.z.moveEnergy;
|
|
1311
|
+
}));
|
|
1312
|
+
/* do_cmd_takeoff: energy is half a turn. */
|
|
1313
|
+
registry.register("takeoff", gated((state, cmd) => {
|
|
1314
|
+
const args = cmd.args ?? {};
|
|
1315
|
+
const handle = typeof args["handle"] === "number" ? args["handle"] : null;
|
|
1316
|
+
if (handle === null)
|
|
1317
|
+
return 0;
|
|
1318
|
+
const obj = gearGet(state.gear, handle);
|
|
1319
|
+
const tval = obj?.tval ?? 0;
|
|
1320
|
+
/* obj_can_takeoff (obj-util.c:794-796) is the takeoff-item filter in
|
|
1321
|
+
* do_cmd_takeoff (cmd-obj.c:251): a sticky item is not selectable, so this
|
|
1322
|
+
* direct command entry likewise aborts silently and spends no energy. */
|
|
1323
|
+
if (obj?.flags.has(OF.STICKY))
|
|
1324
|
+
return 0;
|
|
1325
|
+
if (!invenTakeoff(state, handle))
|
|
1326
|
+
return 0;
|
|
1327
|
+
/* inven_takeoff sets PU_INVEN and calls update_stuff ITSELF (obj-gear.c
|
|
1328
|
+
* L1058-1062), one line before its message - because that message names the
|
|
1329
|
+
* item at its NEW pack letter, and the item has only just stopped being
|
|
1330
|
+
* equipment. The port deferred this to the caller's combine_pack below, which
|
|
1331
|
+
* is after the message: the letter was read off a listing the item was not
|
|
1332
|
+
* in yet. (The old comment here cited L1060 for combine_pack; L1060 is
|
|
1333
|
+
* update_stuff inside inven_takeoff.) */
|
|
1334
|
+
calcInventory(state.gear, deps.constants, calcInvOpts(state, deps));
|
|
1335
|
+
/* inven_takeoff's message (obj-gear.c L1046-1065): the slot wording, then
|
|
1336
|
+
* the item named at its new pack label. */
|
|
1337
|
+
if (obj) {
|
|
1338
|
+
const act = tvalIsMeleeWeapon(tval)
|
|
1339
|
+
? "You were wielding"
|
|
1340
|
+
: tvalIsLauncher(tval) || tvalIsLight(tval)
|
|
1341
|
+
? "You were holding"
|
|
1342
|
+
: "You were wearing";
|
|
1343
|
+
deps.env?.msg?.(`${act} ${describeObject(state, obj)} (${gearLabelFor(state, handle)}).`);
|
|
1344
|
+
}
|
|
1345
|
+
/* combine_pack (which re-runs calc_inventory for inven_takeoff's PU_INVEN,
|
|
1346
|
+
* obj-gear.c L1060) then pack_overflow on the item just taken off
|
|
1347
|
+
* (cmd-obj.c L255-257). */
|
|
1348
|
+
const opts = packOpts(state, deps);
|
|
1349
|
+
combinePack(state.gear, deps.constants, calcInvOpts(state, deps));
|
|
1350
|
+
packOverflow(state, handle, deps.constants, opts);
|
|
1351
|
+
return Math.trunc(state.z.moveEnergy / 2);
|
|
1352
|
+
}));
|
|
1353
|
+
/* do_cmd_drop: energy is half a turn. */
|
|
1354
|
+
registry.register("drop", gated((state, cmd) => {
|
|
1355
|
+
const args = cmd.args ?? {};
|
|
1356
|
+
const handle = typeof args["handle"] === "number" ? args["handle"] : null;
|
|
1357
|
+
if (handle === null)
|
|
1358
|
+
return 0;
|
|
1359
|
+
const obj = gearGet(state.gear, handle);
|
|
1360
|
+
if (!obj)
|
|
1361
|
+
return 0;
|
|
1362
|
+
/* Cannot drop stickied equipment (cmd-obj.c L377-381). The C checks
|
|
1363
|
+
* object_is_equipped && !obj_can_takeoff and aborts before inven_drop, so no
|
|
1364
|
+
* energy is spent and no RNG is drawn. */
|
|
1365
|
+
if (state.actor.player.equipment.includes(handle) &&
|
|
1366
|
+
obj.flags.has(OF.STICKY)) {
|
|
1367
|
+
deps.env?.msg?.("Hmmm, it seems to be stuck.");
|
|
1368
|
+
return 0;
|
|
1369
|
+
}
|
|
1370
|
+
const amt = typeof args["quantity"] === "number" ? args["quantity"] : obj.number;
|
|
1371
|
+
/* Label captured before the drop (inven_drop L1099). */
|
|
1372
|
+
const label = gearLabelFor(state, handle);
|
|
1373
|
+
const result = invenDrop(state, handle, amt, deps.floorEnv);
|
|
1374
|
+
if (!result)
|
|
1375
|
+
return 0;
|
|
1376
|
+
const { dropped, noneLeft, wasEquipped } = result;
|
|
1377
|
+
/* gear_object_for_use excises through gear_excise_object, which re-runs
|
|
1378
|
+
* calc_inventory (obj-gear.c L497) - BEFORE inven_drop's messages, not after
|
|
1379
|
+
* them. It matters for the "1st" letter below, which upstream looks up at
|
|
1380
|
+
* L1157 against the rebuilt listing; `label` above stays the pre-drop one
|
|
1381
|
+
* (L1099), exactly as upstream captures it. */
|
|
1382
|
+
calcInventory(state.gear, deps.constants, calcInvOpts(state, deps));
|
|
1383
|
+
/* inven_drop's messages (obj-gear.c L1120-1165): the drop, then what's
|
|
1384
|
+
* left. Dropping an equipped item omits the take-off line the port's
|
|
1385
|
+
* inven_takeoff does not emit - ledgered. */
|
|
1386
|
+
deps.env?.msg?.(`You drop ${describeObject(state, dropped)} (${label}).`);
|
|
1387
|
+
if (dropped.artifact) {
|
|
1388
|
+
deps.env?.msg?.(`You no longer have the ${describeObject(state, dropped, ODESC.FULL | ODESC.SINGULAR)} (${label}).`);
|
|
1389
|
+
}
|
|
1390
|
+
else {
|
|
1391
|
+
/* The remaining count is the AGGREGATE over every like stack still in the
|
|
1392
|
+
* pack (object_pack_total, L1149), and the letter is the first such
|
|
1393
|
+
* stack's - so dropping 2 of 5 flasks split over slots c and f says
|
|
1394
|
+
* "You have 3 Flasks of oil (1st c)." Suppressed when the item was
|
|
1395
|
+
* equipped, or carries a stack-specific charge / recharging notice
|
|
1396
|
+
* (L1138-1141), in which case the aggregate would contradict it. */
|
|
1397
|
+
let total;
|
|
1398
|
+
let first;
|
|
1399
|
+
let descTarget;
|
|
1400
|
+
if (wasEquipped || packTotalSuppressed(obj)) {
|
|
1401
|
+
first = null;
|
|
1402
|
+
if (noneLeft) {
|
|
1403
|
+
total = 0;
|
|
1404
|
+
descTarget = dropped;
|
|
1405
|
+
}
|
|
1406
|
+
else {
|
|
1407
|
+
total = obj.number;
|
|
1408
|
+
descTarget = obj;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
else {
|
|
1412
|
+
const view = packTotalView(state.gear);
|
|
1413
|
+
({ total, first } = objectPackTotal(view, obj, false));
|
|
1414
|
+
descTarget = total ? obj : dropped;
|
|
1415
|
+
}
|
|
1416
|
+
const name = describeObject(state, descTarget, ODESC.PREFIX | ODESC.FULL | ODESC.ALTNUM, total);
|
|
1417
|
+
if (!first) {
|
|
1418
|
+
deps.env?.msg?.(`You have ${name} (${label}).`);
|
|
1419
|
+
}
|
|
1420
|
+
else {
|
|
1421
|
+
const firstLabel = packLabelFor(state, first);
|
|
1422
|
+
deps.env?.msg?.(total > first.number
|
|
1423
|
+
? `You have ${name} (1st ${firstLabel}).`
|
|
1424
|
+
: `You have ${name} (${firstLabel}).`);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
return Math.trunc(state.z.moveEnergy / 2);
|
|
1428
|
+
}));
|
|
1429
|
+
registry.register("eat", useCommand(deps, (o) => tvalIsEdible(o.tval), USE.SINGLE));
|
|
1430
|
+
/* do_cmd_quaff_potion (cmd-obj.c L917-931): the resume-shape gate, THEN the
|
|
1431
|
+
* potion pick. Unlike do_cmd_eat_food it is gated. */
|
|
1432
|
+
registry.register("quaff", gated(useCommand(deps, (o) => tvalIsPotion(o.tval), USE.SINGLE)));
|
|
1433
|
+
/*
|
|
1434
|
+
* do_cmd_read_scroll (cmd-obj.c L740-758): resume shape, THEN
|
|
1435
|
+
* player_can_read(player, true) - blind / no light / confused / amnesia each
|
|
1436
|
+
* refuse with their own message and cost no turn - and only then the scroll
|
|
1437
|
+
* pick, so the read gate fires before "You have no scrolls to read.".
|
|
1438
|
+
*
|
|
1439
|
+
* Two lanes ported this independently and reached OPPOSITE orderings, because
|
|
1440
|
+
* upstream checks the same condition in two places and each lane found one:
|
|
1441
|
+
* this handler order, and `player_can_read_prereq` hung on the 'r' key entry
|
|
1442
|
+
* (ui-game.c:131), which ui-game.c:596 runs BEFORE the command is ever
|
|
1443
|
+
* pushed. Both are real. The prereq means a blind player pressing 'r' never
|
|
1444
|
+
* reaches the shape-resume prompt at all, while anything that pushes
|
|
1445
|
+
* CMD_READ_SCROLL without going through that key entry still takes
|
|
1446
|
+
* resume-then-read. Collapsing the pair into a single head-of-handler guard
|
|
1447
|
+
* reproduces the keyboard order but breaks the handler's own, so the guard
|
|
1448
|
+
* stays here in C order and the prereq belongs at the port's dispatch layer
|
|
1449
|
+
* next to the key binding - the same split playercan applied to cast/study.
|
|
1450
|
+
*/
|
|
1451
|
+
registry.register("read", gated((state, cmd) => {
|
|
1452
|
+
if (!playerCanRead(state, deps.env ?? {}))
|
|
1453
|
+
return 0;
|
|
1454
|
+
return useCommand(deps, (o) => tvalIsScroll(o.tval), USE.SINGLE)(state, cmd);
|
|
1455
|
+
}));
|
|
1456
|
+
registry.register("use-staff", gated(useCommand(deps, (o) => tvalIsStaff(o.tval), USE.CHARGE)));
|
|
1457
|
+
registry.register("aim-wand", gated(useCommand(deps, (o) => tvalIsWand(o.tval), USE.CHARGE)));
|
|
1458
|
+
/* do_cmd_zap_rod (cmd-obj.c L832): tval_is_rod filter, obj_can_zap guard. */
|
|
1459
|
+
registry.register("zap-rod", gated(useCommand(deps, (o) => tvalIsRod(o.tval), USE.TIMEOUT, {
|
|
1460
|
+
ok: objCanZap,
|
|
1461
|
+
msg: "That rod is still charging.",
|
|
1462
|
+
})));
|
|
1463
|
+
/* do_cmd_activate (cmd-obj.c L866): obj_is_activatable filter (a WEARABLE
|
|
1464
|
+
* with an object_effect - which includes the kind-effect rings that have no
|
|
1465
|
+
* activation), then the obj_can_activate guard. */
|
|
1466
|
+
registry.register("activate", gated(useCommand(deps, objIsActivatable, USE.TIMEOUT, {
|
|
1467
|
+
ok: objCanActivate,
|
|
1468
|
+
msg: "That item is still charging.",
|
|
1469
|
+
})));
|
|
1470
|
+
/* do_cmd_inscribe (cmd-obj.c L179): set the note. Upstream's
|
|
1471
|
+
* quark_add("") does NOT return 0 (z-quark.c L31: it adds a new,
|
|
1472
|
+
* non-zero, empty quark, so obj->note stays truthy and object_desc
|
|
1473
|
+
* renders " {}"). This port intentionally maps "" -> null instead: it is
|
|
1474
|
+
* a deliberate normalization (not literal parity) that keeps note's
|
|
1475
|
+
* truthiness meaningful for objectStackable/objectCombine (object.ts
|
|
1476
|
+
* L844/L920), which already compare/merge notes by truthiness. No
|
|
1477
|
+
* energy; upstream's PN_COMBINE/PN_IGNORE notice + PR_INVEN/PR_EQUIP
|
|
1478
|
+
* redraw are UI bookkeeping this port doesn't model (combine already runs
|
|
1479
|
+
* lazily on the next inven_carry; ignore/display refresh is #25). */
|
|
1480
|
+
registry.register("inscribe", gated((state, cmd) => {
|
|
1481
|
+
const found = commandObject(state, cmd);
|
|
1482
|
+
if (!found)
|
|
1483
|
+
return 0;
|
|
1484
|
+
const raw = cmd.args?.["inscription"];
|
|
1485
|
+
const text = typeof raw === "string" ? raw : "";
|
|
1486
|
+
found.obj.note = text.length > 0 ? text : null;
|
|
1487
|
+
return 0;
|
|
1488
|
+
}));
|
|
1489
|
+
/* do_cmd_uninscribe (cmd-obj.c L153). */
|
|
1490
|
+
registry.register("uninscribe", gated((state, cmd) => {
|
|
1491
|
+
const found = commandObject(state, cmd);
|
|
1492
|
+
if (!found || !objHasInscrip(found.obj))
|
|
1493
|
+
return 0;
|
|
1494
|
+
found.obj.note = null;
|
|
1495
|
+
deps.env?.msg?.("Inscription removed.");
|
|
1496
|
+
return 0;
|
|
1497
|
+
}));
|
|
1498
|
+
/* do_cmd_autoinscribe (cmd-obj.c L219): not gated by
|
|
1499
|
+
* player_get_resume_normal_shape - upstream just no-ops while
|
|
1500
|
+
* shapechanged, with no resume prompt. */
|
|
1501
|
+
registry.register("autoinscribe", (state, _cmd) => {
|
|
1502
|
+
if (playerIsShapechanged(state))
|
|
1503
|
+
return 0;
|
|
1504
|
+
autoinscribeGround(state, deps);
|
|
1505
|
+
autoinscribePack(state, deps);
|
|
1506
|
+
return 0;
|
|
1507
|
+
});
|
|
1508
|
+
/* do_cmd_refill (cmd-obj.c L1071): validate the equipped light, then
|
|
1509
|
+
* refill it from the chosen fuel source. Half a turn on success. */
|
|
1510
|
+
registry.register("refill", gated((state, cmd) => {
|
|
1511
|
+
const light = equippedLight(state);
|
|
1512
|
+
if (!light || !tvalIsLight(light.tval)) {
|
|
1513
|
+
deps.env?.msg?.("You are not wielding a light.");
|
|
1514
|
+
return 0;
|
|
1515
|
+
}
|
|
1516
|
+
if (light.flags.has(OF.NO_FUEL) || !light.flags.has(OF.TAKES_FUEL)) {
|
|
1517
|
+
deps.env?.msg?.("Your light cannot be refilled.");
|
|
1518
|
+
return 0;
|
|
1519
|
+
}
|
|
1520
|
+
const found = commandObject(state, cmd);
|
|
1521
|
+
if (!found || !objCanRefill(state, found.obj))
|
|
1522
|
+
return 0;
|
|
1523
|
+
refillLamp(state, light, found.obj, {
|
|
1524
|
+
fromFloor: found.fromFloor,
|
|
1525
|
+
...(found.handle !== undefined ? { handle: found.handle } : {}),
|
|
1526
|
+
}, deps);
|
|
1527
|
+
return Math.trunc(state.z.moveEnergy / 2);
|
|
1528
|
+
}));
|
|
1529
|
+
}
|
|
1530
|
+
//# sourceMappingURL=obj-cmd.js.map
|